1 /******************************************************************************\
2 Copyright (c) 2005-2020, Intel Corporation
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
7 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8
9 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10
11 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
15 This sample was distributed or derived from the Intel's Media Samples package.
16 The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
17 or https://software.intel.com/en-us/media-client-solutions-support.
18 \**********************************************************************************/
19
20 #include "mfx_samples_config.h"
21
22 #if defined(_WIN32) || defined(_WIN64)
23 #include <windows.h>
24 #endif
25
26 #include "pipeline_transcode.h"
27 #include "transcode_utils.h"
28 #include "sample_utils.h"
29 #include "mfx_vpp_plugin.h"
30 #include "mfx_itt_trace.h"
31 #include <algorithm>
32 #include <cstring>
33 #include <assert.h>
34
35 #include "plugin_loader.h"
36 #include "parameters_dumper.h"
37
38 #include "sample_utils.h"
39
40 // let's use std::max and std::min instead
41 #undef max
42 #undef min
43
44 #ifndef MFX_VERSION
45 #error MFX_VERSION not defined
46 #endif
47
48 using namespace TranscodingSample;
49
50 #ifdef ENABLE_MCTF
51 namespace TranscodingSample
52 {
GetCurParam()53 const sMctfRunTimeParam* sMctfRunTimeParams::GetCurParam()
54 {
55 if (CurIdx >= RunTimeParams.size())
56 return NULL;
57 else
58 return &(RunTimeParams[CurIdx]);
59 }
60
MoveForward()61 void sMctfRunTimeParams::MoveForward()
62 {
63 if(CurIdx < RunTimeParams.size())
64 ++CurIdx;
65 }
66
Restart()67 void sMctfRunTimeParams::Restart()
68 {
69 CurIdx = 0;
70 }
71
Reset()72 void sMctfRunTimeParams::Reset()
73 {
74 CurIdx = 0;
75 RunTimeParams.clear();
76 }
77 }
78 #endif
79
GetFrameInfo(const MfxVideoParamsWrapper & param)80 mfxFrameInfo GetFrameInfo(const MfxVideoParamsWrapper& param)
81 {
82 mfxFrameInfo frameInfo = param.mfx.FrameInfo;
83 auto decPostProc = param.GetExtBuffer<mfxExtDecVideoProcessing>();
84 if(decPostProc)
85 {
86 frameInfo.Width = decPostProc->Out.Width;
87 frameInfo.Height = decPostProc->Out.Height;
88 frameInfo.CropW = decPostProc->Out.CropW;
89 frameInfo.CropH = decPostProc->Out.CropH;
90 }
91
92 return frameInfo;
93 }
94
95 // set structure to define values
sInputParams()96 sInputParams::sInputParams() : __sInputParams()
97 {
98 #ifdef ENABLE_MCTF
99 mctfParam.mode = VPP_FILTER_DISABLED;
100 mctfParam.params.FilterStrength = 0;
101 mctfParam.rtParams.Reset();
102 #ifdef ENABLE_MCTF_EXT
103 mctfParam.params.BitsPerPixelx100k = 0;
104 mctfParam.params.Deblocking = MFX_CODINGOPTION_OFF;
105 mctfParam.params.Overlap = MFX_CODINGOPTION_OFF;
106 mctfParam.params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_2REF;
107 mctfParam.params.MVPrecision = MFX_MVPRECISION_INTEGER;
108 #endif
109 #endif
110 priority = MFX_PRIORITY_NORMAL;
111 libType = MFX_IMPL_SOFTWARE;
112 #if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031)
113 //Adapter type
114 bPrefferiGfx = false;
115 bPrefferdGfx = false;
116 #endif
117 MaxFrameNumber = MFX_INFINITE;
118 pVppCompDstRects = NULL;
119 m_hwdev = NULL;
120 DenoiseLevel=-1;
121 DetailLevel=-1;
122
123 #if (MFX_VERSION >= 1025)
124 MFMode = MFX_MF_DEFAULT;
125 numMFEFrames = 0;
126 mfeTimeout = 0;
127 #endif
128
129 #if MFX_VERSION >= 1022
130 bDecoderPostProcessing = false;
131 bROIasQPMAP = false;
132 #endif
133 }
134
CTranscodingPipeline()135 CTranscodingPipeline::CTranscodingPipeline():
136 m_pmfxBS(NULL),
137 m_pMFXAllocator(NULL),
138 m_hdl(NULL),
139 m_encoderFourCC(0),
140 m_vppCompDumpRenderMode(0),
141 m_hwdev4Rendering(NULL),
142 m_EncSurfaceType(0),
143 m_DecSurfaceType(0),
144 m_bIsVpp(false),
145 m_bIsPlugin(false),
146 m_nTimeout(0),
147 m_bOwnMVCSeqDescMemory(true),
148 m_nID(0),
149 m_AsyncDepth(0),
150 m_nProcessedFramesNum(0),
151 m_bIsJoinSession(false),
152 m_bDecodeEnable(true),
153 m_bEncodeEnable(true),
154 m_nVPPCompEnable(0),
155 m_bUseOpaqueMemory(false),
156 m_LastDecSyncPoint(0),
157 m_pBuffer(NULL),
158 m_pParentPipeline(NULL),
159 m_bIsInit(false),
160 m_NumFramesForReset(0),
161 isHEVCSW(false),
162 m_bInsertIDR(false),
163 m_rawInput(false),
164 m_FrameNumberPreference(0xFFFFFFFF),
165 m_MaxFramesForTranscode(0xFFFFFFFF),
166 m_pBSProcessor(NULL),
167 m_nReqFrameTime(0),
168 m_nOutputFramesNum(0),
169 shouldUseGreedyFormula(false),
170 m_nRotationAngle(0)
171 {
172 MSDK_ZERO_MEMORY(m_RotateParam);
173 MSDK_ZERO_MEMORY(m_mfxDecResponse);
174 MSDK_ZERO_MEMORY(m_mfxEncResponse);
175 MSDK_ZERO_MEMORY(m_Request);
176
177 #if MFX_VERSION >= 1022
178 m_bUseQPMap = 0;
179 m_QPmapWidth = 0;
180 m_QPmapHeight = 0;
181 m_GOPSize = 0;
182 m_QPforI = 0;
183 m_QPforP = 0;
184 m_nSubmittedFramesNum = 0;
185 #endif //MFX_VERSION >= 1022
186
187 inputStatistics.SetDirection(MSDK_STRING("Input"));
188 outputStatistics.SetDirection(MSDK_STRING("Output"));
189
190 m_numEncoders = 0;
191 m_encoderFourCC = 0;
192 m_libvaBackend = 0;
193 statisticsWindowSize=0;
194 m_bIsFieldWeaving = false;
195 m_bIsFieldSplitting = false;
196 m_bUseOverlay = false;
197 m_bForceStop = false;
198 m_bIsInterOrJoined = false;
199 m_bRobustFlag = false;
200 m_bSoftGpuHangRecovery = false;
201 m_nRotationAngle = 0;
202 m_bROIasQPMAP = false;
203 m_bExtMBQP = false;
204 } //CTranscodingPipeline::CTranscodingPipeline()
205
~CTranscodingPipeline()206 CTranscodingPipeline::~CTranscodingPipeline()
207 {
208 Close();
209 } //CTranscodingPipeline::CTranscodingPipeline()
210
CheckRequiredAPIVersion(mfxVersion & version,sInputParams * pParams)211 mfxStatus CTranscodingPipeline::CheckRequiredAPIVersion(mfxVersion& version, sInputParams *pParams)
212 {
213 MSDK_CHECK_POINTER(pParams, MFX_ERR_NULL_PTR);
214
215 if (pParams->bIsMVC && !CheckVersion(&version, MSDK_FEATURE_MVC)) {
216 msdk_printf(MSDK_STRING("error: MVC is not supported in the %d.%d API version\n"),
217 version.Major, version.Minor);
218 return MFX_ERR_UNSUPPORTED;
219
220 }
221 if ((pParams->DecodeId == MFX_CODEC_JPEG) && !CheckVersion(&version, MSDK_FEATURE_JPEG_DECODE)) {
222 msdk_printf(MSDK_STRING("error: Jpeg decoder is not supported in the %d.%d API version\n"),
223 version.Major, version.Minor);
224 return MFX_ERR_UNSUPPORTED;
225 }
226 if ((pParams->EncodeId == MFX_CODEC_JPEG) && !CheckVersion(&version, MSDK_FEATURE_JPEG_ENCODE)) {
227 msdk_printf(MSDK_STRING("error: Jpeg encoder is not supported in the %d.%d API version\n"),
228 version.Major, version.Minor);
229 return MFX_ERR_UNSUPPORTED;
230 }
231
232 if ((pParams->bLABRC || pParams->nLADepth) && !CheckVersion(&version, MSDK_FEATURE_LOOK_AHEAD)) {
233 msdk_printf(MSDK_STRING("error: Look Ahead is not supported in the %d.%d API version\n"),
234 version.Major, version.Minor);
235 return MFX_ERR_UNSUPPORTED;
236 }
237
238 return MFX_ERR_NONE;
239 }
240
241 // initialize decode part
DecodePreInit(sInputParams * pParams)242 mfxStatus CTranscodingPipeline::DecodePreInit(sInputParams *pParams)
243 {
244 // initialize decode pert
245 mfxStatus sts = MFX_ERR_NONE;
246
247 if (m_bDecodeEnable)
248 {
249 if (CheckVersion(&m_Version, MSDK_FEATURE_PLUGIN_API))
250 {
251 /* Here we actually define the following codec initialization scheme:
252 * 1. If plugin path or guid is specified: we load user-defined plugin (example: VP9 sample decoder plugin)
253 * 2. If plugin path not specified:
254 * 2.a) we check if codec is distributed as a mediasdk plugin and load it if yes
255 * 2.b) if codec is not in the list of mediasdk plugins, we assume, that it is supported inside mediasdk library
256 */
257 if (pParams->decoderPluginParams.type == MFX_PLUGINLOAD_TYPE_FILE && msdk_strnlen(pParams->decoderPluginParams.strPluginPath,sizeof(pParams->decoderPluginParams.strPluginPath)))
258 {
259 m_pUserDecoderModule.reset(new MFXVideoUSER(*m_pmfxSession.get()));
260 m_pUserDecoderPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_DECODE, *m_pmfxSession.get(), pParams->decoderPluginParams.pluginGuid, 1, pParams->decoderPluginParams.strPluginPath, (mfxU32)msdk_strnlen(pParams->decoderPluginParams.strPluginPath,sizeof(pParams->decoderPluginParams.strPluginPath))));
261 if (m_pUserDecoderPlugin.get() == NULL) sts = MFX_ERR_UNSUPPORTED;
262 }
263 else
264 {
265 bool isDefaultPlugin = false;
266 if (AreGuidsEqual(pParams->decoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL))
267 {
268 pParams->decoderPluginParams.pluginGuid = msdkGetPluginUID(pParams->libType, MSDK_VDECODE, pParams->DecodeId);
269 isDefaultPlugin=true;
270 }
271 if (!AreGuidsEqual(pParams->decoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL))
272 {
273 m_pUserDecoderPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_DECODE, *m_pmfxSession.get(), pParams->decoderPluginParams.pluginGuid, 1));
274 if (m_pUserDecoderPlugin.get() == NULL) sts = MFX_ERR_UNSUPPORTED;
275 }
276 if(sts==MFX_ERR_UNSUPPORTED)
277 {
278 msdk_printf(isDefaultPlugin ?
279 MSDK_STRING("Default plugin cannot be loaded (possibly you have to define plugin explicitly)\n")
280 : MSDK_STRING("Explicitly specified plugin cannot be loaded.\n"));
281 }
282 }
283 MSDK_CHECK_STATUS(sts, "LoadPlugin failed");
284 }
285
286 // create decoder
287 if (!m_bUseOverlay)
288 {
289 m_pmfxDEC.reset(new MFXVideoDECODE(*m_pmfxSession.get()));
290 }
291
292 // set video type in parameters
293 m_mfxDecParams.mfx.CodecId = pParams->DecodeId;
294
295 // configure specific decoder parameters
296 sts = InitDecMfxParams(pParams);
297 if (MFX_ERR_MORE_DATA == sts)
298 {
299 m_pmfxDEC.reset(NULL);
300 return sts;
301 }
302 else
303 {
304 MSDK_CHECK_STATUS(sts, "InitDecMfxParams failed");
305 }
306 }
307 else
308 {
309 m_mfxDecParams = m_pParentPipeline->GetDecodeParam();
310 auto mvc = m_mfxDecParams.AddExtBuffer<mfxExtMVCSeqDesc>();
311 *mvc = m_pParentPipeline->GetDecMVCSeqDesc();
312 m_bOwnMVCSeqDescMemory = false;
313 }
314
315 if (pParams->nFPS)
316 {
317 this->m_nReqFrameTime = 1000000 / pParams->nFPS;
318 }
319
320 return sts;
321
322 } //mfxStatus CTranscodingPipeline::Init(sInputParams *pParams)
323
VPPPreInit(sInputParams * pParams)324 mfxStatus CTranscodingPipeline::VPPPreInit(sInputParams *pParams)
325 {
326 mfxStatus sts = MFX_ERR_NONE;
327 bool bVppCompInitRequire = false;
328 m_bIsFieldWeaving = false;
329 m_bIsFieldSplitting = false;
330
331 if (((pParams->eModeExt == VppComp) || (pParams->eModeExt == VppCompOnly)) &&
332 (pParams->eMode == Source))
333 bVppCompInitRequire = true;
334
335 // Obtaining decoder output FourCC - in case of inter-session, just take it from params, in intra-session case, take it from parent session
336 // In inter-session case, we'll enable chroma-changing VPP only in encoding session, and only if decoderFourCC!=encoderFourCC
337 mfxU32 decoderFourCC = m_bDecodeEnable ? m_mfxDecParams.mfx.FrameInfo.FourCC : m_pParentPipeline->GetDecodeParam().mfx.FrameInfo.FourCC;
338
339 if (m_bEncodeEnable || m_bDecodeEnable)
340 {
341 if (m_mfxDecParams.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_FIELD_SINGLE &&
342 pParams->EncodeId != MFX_CODEC_HEVC && !pParams->bEnableDeinterlacing)
343 {
344 m_bIsFieldWeaving = true;
345 m_bIsVpp = true;
346 }
347
348 if ((m_mfxDecParams.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_FIELD_TFF || m_mfxDecParams.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_FIELD_BFF || m_mfxDecParams.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_UNKNOWN)
349 && pParams->EncodeId == MFX_CODEC_HEVC && pParams->DecodeId != MFX_CODEC_HEVC && !pParams->bEnableDeinterlacing)
350 {
351 m_bIsFieldSplitting = true;
352 m_bIsVpp = true;
353 m_mfxVppParams.vpp.In.PicStruct = MFX_PICSTRUCT_UNKNOWN;
354 }
355
356 if ( (GetFrameInfo(m_mfxDecParams).CropW != pParams->nDstWidth && pParams->nDstWidth) ||
357 (GetFrameInfo(m_mfxDecParams).CropH != pParams->nDstHeight && pParams->nDstHeight) ||
358 (pParams->bEnableDeinterlacing) || (pParams->DenoiseLevel!=-1) || (pParams->DetailLevel!=-1) || (pParams->FRCAlgorithm) ||
359 (bVppCompInitRequire) || (pParams->fieldProcessingMode) ||
360 #ifdef ENABLE_MCTF
361 (VPP_FILTER_DISABLED != pParams->mctfParam.mode) ||
362 #endif
363 (pParams->EncoderFourCC && decoderFourCC && pParams->EncoderFourCC != decoderFourCC && m_bEncodeEnable))
364 {
365 if (m_bIsFieldWeaving || m_bIsFieldSplitting)
366 {
367 msdk_printf(MSDK_STRING("ERROR: Field weaving or Field Splitting is enabled according to streams parameters. Other VPP filters cannot be used in this mode, please remove corresponding options.\n"));
368 return MFX_ERR_UNSUPPORTED;
369 }
370
371 m_bIsVpp = true;
372 }
373
374 if (m_bIsVpp)
375 {
376 sts = InitVppMfxParams(pParams);
377 MSDK_CHECK_STATUS(sts, "InitVppMfxParams failed");
378 }
379
380 if (pParams->nRotationAngle) // plugin was requested
381 {
382 m_bIsPlugin = true;
383 sts = InitPluginMfxParams(pParams);
384 MSDK_CHECK_STATUS(sts, "InitPluginMfxParams failed");
385 sts = LoadGenericPlugin();
386 MSDK_CHECK_STATUS(sts, "LoadGenericPlugin failed");
387 }
388
389 if (!m_bIsPlugin && m_bIsVpp) // only VPP was requested
390 {
391 m_pmfxVPP.reset(new MFXVideoMultiVPP(*m_pmfxSession.get()));
392 }
393 }
394
395 return sts;
396
397 } //mfxStatus CTranscodingPipeline::VPPInit(sInputParams *pParams)
398
EncodePreInit(sInputParams * pParams)399 mfxStatus CTranscodingPipeline::EncodePreInit(sInputParams *pParams)
400 {
401
402 mfxStatus sts = MFX_ERR_NONE;
403
404 if (m_bEncodeEnable)
405 {
406 if(pParams->EncodeId != MFX_CODEC_DUMP)
407 {
408 if (CheckVersion(&m_Version, MSDK_FEATURE_PLUGIN_API) && (m_pUserEncPlugin.get() == NULL))
409 {
410 /* Here we actually define the following codec initialization scheme:
411 * 1. If plugin path or guid is specified: we load user-defined plugin (example: HEVC encoder plugin)
412 * 2. If plugin path not specified:
413 * 2.a) we check if codec is distributed as a mediasdk plugin and load it if yes
414 * 2.b) if codec is not in the list of mediasdk plugins, we assume, that it is supported inside mediasdk library
415 */
416 if (pParams->encoderPluginParams.type == MFX_PLUGINLOAD_TYPE_FILE && msdk_strnlen(pParams->encoderPluginParams.strPluginPath,sizeof(pParams->encoderPluginParams.strPluginPath)))
417 {
418 m_pUserEncoderModule.reset(new MFXVideoUSER(*m_pmfxSession.get()));
419 m_pUserEncoderPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_ENCODE, *m_pmfxSession.get(), pParams->encoderPluginParams.pluginGuid, 1, pParams->encoderPluginParams.strPluginPath, (mfxU32)msdk_strnlen(pParams->encoderPluginParams.strPluginPath,sizeof(pParams->encoderPluginParams.strPluginPath))));
420 if (m_pUserEncoderPlugin.get() == NULL) sts = MFX_ERR_UNSUPPORTED;
421 }
422 else
423 {
424 bool isDefaultPlugin = false;
425 if (AreGuidsEqual(pParams->encoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL))
426 {
427 pParams->encoderPluginParams.pluginGuid = msdkGetPluginUID(pParams->libType, MSDK_VENCODE, pParams->EncodeId);
428 isDefaultPlugin = true;
429 }
430 if (!AreGuidsEqual(pParams->encoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL))
431 {
432 m_pUserEncoderPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_ENCODE, *m_pmfxSession.get(), pParams->encoderPluginParams.pluginGuid, 1));
433 if (m_pUserEncoderPlugin.get() == NULL) sts = MFX_ERR_UNSUPPORTED;
434 }
435 if(sts==MFX_ERR_UNSUPPORTED)
436 {
437 msdk_printf(MSDK_STRING("%s"), isDefaultPlugin ?
438 MSDK_STRING("Default plugin cannot be loaded (possibly you have to define plugin explicitly)\n")
439 : MSDK_STRING("Explicitly specified plugin cannot be loaded.\n"));
440 }
441 }
442 MSDK_CHECK_STATUS(sts, "LoadPlugin failed");
443 }
444
445 // create encoder
446 m_pmfxENC.reset(new MFXVideoENCODE(*m_pmfxSession.get()));
447
448 if (m_nVPPCompEnable == VppCompOnlyEncode)
449 {
450 pParams->EncoderFourCC = MFX_FOURCC_NV12;
451 }
452
453 sts = InitEncMfxParams(pParams);
454 MSDK_CHECK_STATUS(sts, "InitEncMfxParams failed");
455
456 // Querying parameters
457 mfxU16 ioPattern = m_mfxEncParams.IOPattern;
458 mfxU16 initialTargetKbps = m_mfxEncParams.mfx.TargetKbps;
459 auto co2 = m_mfxEncParams.GetExtBuffer<mfxExtCodingOption2>();
460
461 msdk_stringstream str1, str2;
462 CParametersDumper().SerializeVideoParamStruct(str1, MSDK_STRING(""), m_mfxEncParams);
463
464 sts = m_pmfxENC->Query(&m_mfxEncParams, &m_mfxEncParams);
465
466 CParametersDumper().SerializeVideoParamStruct(str2, MSDK_STRING(""), m_mfxEncParams);
467
468 m_mfxEncParams.IOPattern=ioPattern; // Workaround for a problem: Query changes IOPattern incorrectly
469
470 if (sts == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM)
471 {
472 if (co2 && co2->BitrateLimit != MFX_CODINGOPTION_OFF && initialTargetKbps != m_mfxEncParams.mfx.TargetKbps)
473 {
474 msdk_printf(MSDK_STRING("[WARNING] -BitrateLimit:on, target bitrate was changed\n"));
475 }
476
477 msdk_printf(MSDK_STRING("[WARNING] Configuration changed on the Query() call\n"));
478
479 CParametersDumper().ShowConfigurationDiff(str1, str2);
480 MSDK_IGNORE_MFX_STS(sts, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM);
481 }
482
483 MSDK_CHECK_STATUS(sts, "m_pmfxENC->Query failed");
484 }
485 else
486 {
487 //--- This one is required for YUV output
488 m_mfxEncParams.mfx.CodecId = pParams->EncodeId;
489 }
490
491 }
492 return sts;
493
494 } // mfxStatus CTranscodingPipeline::EncodeInit(sInputParams *pParams)
495
PreEncPreInit(sInputParams * pParams)496 mfxStatus CTranscodingPipeline::PreEncPreInit(sInputParams *pParams)
497 {
498 mfxStatus sts = MFX_ERR_NONE;
499 // PreInit is allowed in decoder session only
500 if (pParams->bEnableExtLA && m_bDecodeEnable)
501 {
502 /* Here we actually define the following codec initialization scheme:
503 * a) we check if codec is distributed as a user plugin and load it if yes
504 * b) we check if codec is distributed as a mediasdk plugin and load it if yes
505 * c) if codec is not in the list of user plugins or mediasdk plugins, we assume, that it is supported inside mediasdk library
506 */
507
508 m_pUserEncPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_ENCODE, *m_pmfxSession.get(), MFX_PLUGINID_H264LA_HW, 1));
509 if (m_pUserEncPlugin.get() == NULL) sts = MFX_ERR_UNSUPPORTED;
510
511 // create encoder
512 m_pmfxPreENC.reset(new MFXVideoENC(*m_pmfxSession.get()));
513
514 sts = InitPreEncMfxParams(pParams);
515 MSDK_CHECK_STATUS(sts, "InitPreEncMfxParams failed");
516 }
517 return sts;
518
519 }
520
GetDecodeParam()521 mfxVideoParam CTranscodingPipeline::GetDecodeParam() {
522 if (m_bIsVpp)
523 {
524 mfxVideoParam tmp = m_mfxDecParams;
525 tmp.mfx.FrameInfo = m_mfxVppParams.vpp.Out;
526 return tmp;
527 }
528 else if (m_bIsPlugin)
529 {
530 mfxVideoParam tmp = m_mfxDecParams;
531 tmp.mfx.FrameInfo = m_mfxPluginParams.mfx.FrameInfo;
532 return tmp;
533 }
534
535 return m_mfxDecParams;
536 };
537 // 1 ms provides better result in range [0..5] ms
538 enum
539 {
540 TIME_TO_SLEEP = 1
541 };
542
DecodeOneFrame(ExtendedSurface * pExtSurface)543 mfxStatus CTranscodingPipeline::DecodeOneFrame(ExtendedSurface *pExtSurface)
544 {
545 MFX_ITT_TASK("DecodeOneFrame");
546 MSDK_CHECK_POINTER(pExtSurface, MFX_ERR_NULL_PTR);
547
548 mfxStatus sts = MFX_ERR_MORE_SURFACE;
549 mfxFrameSurface1 *pmfxSurface = NULL;
550 pExtSurface->pSurface = NULL;
551
552 //--- Time measurements
553 if (statisticsWindowSize)
554 {
555 inputStatistics.StopTimeMeasurementWithCheck();
556 inputStatistics.StartTimeMeasurement();
557 }
558
559 CTimer DevBusyTimer;
560 DevBusyTimer.Start();
561 while (MFX_ERR_MORE_DATA == sts || MFX_ERR_MORE_SURFACE == sts || MFX_ERR_NONE < sts)
562 {
563 if (m_rawInput)
564 {
565 pExtSurface->pSurface = GetFreeSurface(false, MSDK_SURFACE_WAIT_INTERVAL);
566 sts = m_pBSProcessor->GetInputFrame(pExtSurface->pSurface);
567 if(sts != MFX_ERR_NONE)
568 return sts;
569 }
570 else if (MFX_WRN_DEVICE_BUSY == sts)
571 {
572 WaitForDeviceToBecomeFree(*m_pmfxSession,m_LastDecSyncPoint,sts);
573 }
574 else if (MFX_ERR_MORE_DATA == sts)
575 {
576 sts = m_pBSProcessor->GetInputBitstream(&m_pmfxBS); // read more data to input bit stream
577 MSDK_BREAK_ON_ERROR(sts);
578 }
579 else if (MFX_ERR_MORE_SURFACE == sts)
580 {
581 // Find new working surface
582 pmfxSurface = GetFreeSurface(true, MSDK_SURFACE_WAIT_INTERVAL);
583 {
584 std::unique_lock<std::mutex> lock(m_mStopSession);
585 if (m_bForceStop)
586 {
587 lock.unlock();
588 m_nTimeout = 0;
589 // add surfaces in queue for all sinks
590 NoMoreFramesSignal();
591 return MFX_WRN_VALUE_NOT_CHANGED;
592 }
593 }
594 MSDK_CHECK_POINTER_SAFE(pmfxSurface, MFX_ERR_MEMORY_ALLOC, msdk_printf(MSDK_STRING("ERROR: No free surfaces in decoder pool (during long period)\n"))); // return an error if a free surface wasn't found
595 }
596
597 if (!m_rawInput)
598 {
599 sts = m_pmfxDEC->DecodeFrameAsync(m_pmfxBS, pmfxSurface, &pExtSurface->pSurface, &pExtSurface->Syncp);
600 }
601
602 if ( (MFX_WRN_DEVICE_BUSY == sts) &&
603 (DevBusyTimer.GetTime() > MSDK_WAIT_INTERVAL/1000) )
604 {
605 msdk_printf(MSDK_STRING("ERROR: Decoder device busy (during long period)\n"));
606 return MFX_ERR_DEVICE_FAILED;
607 }
608
609 if (sts==MFX_ERR_NONE)
610 {
611 m_LastDecSyncPoint = pExtSurface->Syncp;
612 }
613 // ignore warnings if output is available,
614 if (MFX_ERR_NONE < sts && pExtSurface->Syncp)
615 {
616 sts = MFX_ERR_NONE;
617 }
618
619 } //while processing
620
621 // HEVC SW requires additional synchronization
622 if( MFX_ERR_NONE == sts && isHEVCSW)
623 {
624 sts = m_pmfxSession->SyncOperation(pExtSurface->Syncp, MSDK_WAIT_INTERVAL);
625 HandlePossibleGpuHang(sts);
626 MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "Decode: SyncOperation failed");
627 }
628 return sts;
629
630 } // mfxStatus CTranscodingPipeline::DecodeOneFrame(ExtendedSurface *pExtSurface)
DecodeLastFrame(ExtendedSurface * pExtSurface)631 mfxStatus CTranscodingPipeline::DecodeLastFrame(ExtendedSurface *pExtSurface)
632 {
633 MFX_ITT_TASK("DecodeLastFrame");
634 mfxFrameSurface1 *pmfxSurface = NULL;
635 mfxStatus sts = MFX_ERR_MORE_SURFACE;
636
637 //--- Time measurements
638 if (statisticsWindowSize)
639 {
640 inputStatistics.StopTimeMeasurementWithCheck();
641 inputStatistics.StartTimeMeasurement();
642 }
643
644 CTimer DevBusyTimer;
645 DevBusyTimer.Start();
646 // retrieve the buffered decoded frames
647 while (MFX_ERR_MORE_SURFACE == sts || MFX_WRN_DEVICE_BUSY == sts)
648 {
649 if (m_rawInput)
650 {
651 pExtSurface->pSurface = GetFreeSurface(false, MSDK_SURFACE_WAIT_INTERVAL);
652 sts = m_pBSProcessor->GetInputFrame(pExtSurface->pSurface);
653 }
654 else if (MFX_WRN_DEVICE_BUSY == sts)
655 {
656 WaitForDeviceToBecomeFree(*m_pmfxSession,m_LastDecSyncPoint,sts);
657 }
658
659 if (!m_rawInput)
660 {
661 // find new working surface
662 pmfxSurface = GetFreeSurface(true, MSDK_SURFACE_WAIT_INTERVAL);
663 MSDK_CHECK_POINTER_SAFE(pmfxSurface, MFX_ERR_MEMORY_ALLOC, msdk_printf(MSDK_STRING("ERROR: No free surfaces in decoder pool (during long period)\n"))); // return an error if a free surface wasn't found
664 sts = m_pmfxDEC->DecodeFrameAsync(NULL, pmfxSurface, &pExtSurface->pSurface, &pExtSurface->Syncp);
665 }
666
667 if ( (MFX_WRN_DEVICE_BUSY == sts) &&
668 (DevBusyTimer.GetTime() > MSDK_WAIT_INTERVAL/1000) )
669 {
670 msdk_printf(MSDK_STRING("ERROR: Decoder device busy (during long period)\n"));
671 return MFX_ERR_DEVICE_FAILED;
672 }
673 }
674
675 // HEVC SW requires additional synchronization
676 if( MFX_ERR_NONE == sts && isHEVCSW)
677 {
678 sts = m_pmfxSession->SyncOperation(pExtSurface->Syncp, MSDK_WAIT_INTERVAL);
679 HandlePossibleGpuHang(sts);
680 MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "Decode: SyncOperation failed");
681 }
682
683 return sts;
684 }
685
VPPOneFrame(ExtendedSurface * pSurfaceIn,ExtendedSurface * pExtSurface)686 mfxStatus CTranscodingPipeline::VPPOneFrame(ExtendedSurface *pSurfaceIn, ExtendedSurface *pExtSurface)
687 {
688 MFX_ITT_TASK("VPPOneFrame");
689 MSDK_CHECK_POINTER(pExtSurface, MFX_ERR_NULL_PTR);
690
691 // find/wait for a free working surface
692 auto out_surface = GetFreeSurface(false, MSDK_SURFACE_WAIT_INTERVAL);
693 MSDK_CHECK_POINTER_SAFE(out_surface, MFX_ERR_MEMORY_ALLOC, msdk_printf(MSDK_STRING("ERROR: No free surfaces for VPP in encoder pool (during long period)\n"))); // return an error if a free surface wasn't found
694
695 // make sure picture structure has the initial value
696 // surfaces are reused and VPP may change this parameter in certain configurations
697 out_surface->Info.PicStruct = m_mfxVppParams.vpp.Out.PicStruct ? m_mfxVppParams.vpp.Out.PicStruct : (m_bEncodeEnable ? m_mfxEncParams : m_mfxDecParams).mfx.FrameInfo.PicStruct;
698
699 pExtSurface->pSurface = out_surface;
700 mfxStatus sts = MFX_ERR_NONE;
701
702 #ifdef ENABLE_MCTF
703 const auto MCTFCurParam = m_MctfRTParams.GetCurParam();
704 bool applyMCTF = !!MCTFCurParam;
705 if (pSurfaceIn->pSurface)
706 {
707 auto surface = static_cast<mfxFrameSurfaceWrap*>(pSurfaceIn->pSurface);
708 if (applyMCTF)
709 {
710 auto mctf = surface->AddExtBuffer<mfxExtVppMctf>();
711 mctf->FilterStrength = MCTFCurParam->FilterStrength;
712 #if defined ENABLE_MCTF_EXT
713 mctf->BitsPerPixelx100k = mfxU32(MCTF_LOSSLESS_BPP * MCTF_BITRATE_MULTIPLIER);
714 mctf->Deblocking = MFX_CODINGOPTION_OFF;
715 #endif
716 m_MctfRTParams.MoveForward();
717 }
718 else
719 {
720 surface->RemoveExtBuffer<mfxExtVppMctf>();
721 }
722 }
723 #endif
724
725 for(;;)
726 {
727 sts = m_pmfxVPP->RunFrameVPPAsync(pSurfaceIn->pSurface, out_surface, NULL, &pExtSurface->Syncp);
728
729 if (MFX_ERR_NONE < sts && !pExtSurface->Syncp) // repeat the call if warning and no output
730 {
731 if (MFX_WRN_DEVICE_BUSY == sts)
732 MSDK_SLEEP(1); // wait if device is busy
733 }
734 else if (MFX_ERR_NONE < sts && pExtSurface->Syncp)
735 {
736 sts = MFX_ERR_NONE; // ignore warnings if output is available
737 break;
738 }
739 else
740 {
741 break;
742 }
743 }
744 return sts;
745
746 } // mfxStatus CTranscodingPipeline::DecodeOneFrame(ExtendedSurface *pExtSurface)
747
EncodeOneFrame(ExtendedSurface * pExtSurface,mfxBitstreamWrapper * pBS)748 mfxStatus CTranscodingPipeline::EncodeOneFrame(ExtendedSurface *pExtSurface, mfxBitstreamWrapper *pBS)
749 {
750 mfxStatus sts = MFX_ERR_NONE;
751
752 if (!pBS->Data)
753 {
754 sts = AllocateSufficientBuffer(pBS);
755 MSDK_CHECK_STATUS(sts, "AllocateSufficientBuffer failed");
756 }
757
758 for (;;)
759 {
760 // at this point surface for encoder contains either a frame from file or a frame processed by vpp
761 sts = m_pmfxENC->EncodeFrameAsync(pExtSurface->pEncCtrl, pExtSurface->pSurface, pBS, &pExtSurface->Syncp);
762
763 if (MFX_ERR_NONE < sts && !pExtSurface->Syncp) // repeat the call if warning and no output
764 {
765 if (MFX_WRN_DEVICE_BUSY == sts)
766 MSDK_SLEEP(TIME_TO_SLEEP); // wait if device is busy
767 }
768 else if (MFX_ERR_NONE < sts && pExtSurface->Syncp)
769 {
770 sts = MFX_ERR_NONE; // ignore warnings if output is available
771 break;
772 }
773 else if (MFX_ERR_NOT_ENOUGH_BUFFER == sts)
774 {
775 sts = AllocateSufficientBuffer(pBS);
776 MSDK_CHECK_STATUS(sts, "AllocateSufficientBuffer failed");
777 }
778 else
779 {
780 break;
781 }
782 }
783 return sts;
784
785 } //CTranscodingPipeline::EncodeOneFrame(ExtendedSurface *pExtSurface)
786
PreEncOneFrame(ExtendedSurface * pInSurface,ExtendedSurface * pOutSurface)787 mfxStatus CTranscodingPipeline::PreEncOneFrame(ExtendedSurface *pInSurface, ExtendedSurface *pOutSurface)
788 {
789 mfxStatus sts = MFX_ERR_NONE;
790 PreEncAuxBuffer* pAux = NULL;
791
792 for (mfxU32 i = 0; i < MSDK_WAIT_INTERVAL; i += TIME_TO_SLEEP)
793 {
794 pAux = GetFreePreEncAuxBuffer();
795 if (pAux)
796 {
797 break;
798 }
799 else
800 {
801 MSDK_SLEEP(TIME_TO_SLEEP);
802 }
803 }
804 MSDK_CHECK_POINTER(pAux, MFX_ERR_MEMORY_ALLOC);
805 for (;;)
806 {
807 pAux->encInput.InSurface = pInSurface->pSurface;
808 // at this point surface for encoder contains either a frame from file or a frame processed by vpp
809 sts = m_pmfxPreENC->ProcessFrameAsync(&pAux->encInput, &pAux->encOutput, &pOutSurface->Syncp );
810
811 if (MFX_ERR_NONE < sts && !pOutSurface->Syncp) // repeat the call if warning and no output
812 {
813 if (MFX_WRN_DEVICE_BUSY == sts)
814 MSDK_SLEEP(TIME_TO_SLEEP); // wait if device is busy
815 }
816 else if (MFX_ERR_NONE <= sts && pOutSurface->Syncp)
817 {
818 LockPreEncAuxBuffer(pAux);
819 pOutSurface->pAuxCtrl = pAux;
820 MSDK_CHECK_POINTER(pAux->encOutput.ExtParam, MFX_ERR_NULL_PTR);
821 MSDK_CHECK_NOT_EQUAL(pAux->encOutput.NumExtParam, 1, MFX_ERR_UNSUPPORTED);
822 pOutSurface->pSurface = ((mfxExtLAFrameStatistics *) pAux->encOutput.ExtParam[0])->OutSurface;
823 sts = MFX_ERR_NONE; // ignore warnings if output is available
824 break;
825 }
826 else
827 {
828 break;
829 }
830 }
831 return sts;
832 }
833
834 // signal that there are no more frames
NoMoreFramesSignal()835 void CTranscodingPipeline::NoMoreFramesSignal()
836 {
837 SafetySurfaceBuffer *pNextBuffer = m_pBuffer;
838
839 // For transcoding pipelines (PipelineMode::Native) this pointer is null
840 if (!pNextBuffer)
841 return;
842
843 ExtendedSurface surf={};
844 pNextBuffer->AddSurface(surf);
845
846 /*if 1_to_N mode */
847 if (0 == m_nVPPCompEnable)
848 {
849 while (pNextBuffer->m_pNext)
850 {
851 pNextBuffer = pNextBuffer->m_pNext;
852 pNextBuffer->AddSurface(surf);
853 }
854 }
855 }
856
StopSession()857 void CTranscodingPipeline::StopSession()
858 {
859 std::lock_guard<std::mutex> guard(m_mStopSession);
860 m_bForceStop = true;
861
862 msdk_stringstream ss;
863 ss << MSDK_STRING("session [") << GetSessionText() << MSDK_STRING("] m_bForceStop is set") << std::endl;
864 msdk_printf(MSDK_STRING("%s"), ss.str().c_str());
865 }
866
IsOverlayUsed()867 bool CTranscodingPipeline::IsOverlayUsed()
868 {
869 return m_bUseOverlay;
870 }
871
Decode()872 mfxStatus CTranscodingPipeline::Decode()
873 {
874 mfxStatus sts = MFX_ERR_NONE;
875
876 ExtendedSurface DecExtSurface = {0};
877 ExtendedSurface VppExtSurface = {0};
878 ExtendedSurface PreEncExtSurface = {0};
879 bool shouldReadNextFrame=true;
880
881 SafetySurfaceBuffer *pNextBuffer = m_pBuffer;
882 bool bEndOfFile = false;
883 bool bLastCycle = false;
884 time_t start = time(0);
885
886 {
887 std::unique_lock<std::mutex> lock(m_mStopSession);
888 if (m_bForceStop)
889 {
890 lock.unlock();
891 // add surfaces in queue for all sinks
892 NoMoreFramesSignal();
893 return MFX_WRN_VALUE_NOT_CHANGED;
894 }
895 }
896
897 if (m_bUseOverlay)
898 {
899 PreEncExtSurface.pSurface = m_pSurfaceDecPool[0];
900
901 if (pNextBuffer->GetLength() == 0)
902 {
903 // add surfaces in queue for all sinks
904 pNextBuffer->AddSurface(PreEncExtSurface);
905 m_nProcessedFramesNum++;
906 }
907 return MFX_ERR_NONE;
908 }
909
910 while (MFX_ERR_NONE == sts)
911 {
912 pNextBuffer = m_pBuffer;
913
914 if (time(0) - start >= m_nTimeout)
915 bLastCycle = true;
916
917 if (bLastCycle)
918 SetNumFramesForReset(0);
919
920 msdk_tick nBeginTime = msdk_time_get_tick(); // microseconds.
921
922 if(shouldReadNextFrame)
923 {
924 if (!bEndOfFile)
925 {
926 if (!m_bUseOverlay)
927 {
928 sts = DecodeOneFrame(&DecExtSurface);
929 if (MFX_ERR_MORE_DATA == sts)
930 {
931 sts = bLastCycle ? DecodeLastFrame(&DecExtSurface) : MFX_ERR_MORE_DATA;
932 bEndOfFile = bLastCycle ? true : false;
933 }
934 }
935 else
936 {
937 // Use preloaded overlay frame
938 DecExtSurface.pSurface = m_pSurfaceDecPool[0];
939 sts = MFX_ERR_NONE;
940 }
941 }
942 else
943 {
944 sts = DecodeLastFrame(&DecExtSurface);
945 }
946
947 if (sts == MFX_ERR_NONE)
948 {
949 // print statistics if m_nProcessedFramesNum is multiple of
950 // statisticsWindowSize OR we at the end of file AND
951 // statisticsWindowSize is not zero
952 if (statisticsWindowSize && m_nProcessedFramesNum &&
953 ((0 == m_nProcessedFramesNum % statisticsWindowSize) || bEndOfFile)
954 )
955 {
956 inputStatistics.PrintStatistics(GetPipelineID());
957 inputStatistics.ResetStatistics();
958 }
959 }
960 if (sts == MFX_ERR_MORE_DATA && (m_pmfxVPP.get() || m_pmfxPreENC.get()))
961 {
962 DecExtSurface.pSurface = NULL; // to get buffered VPP or ENC frames
963 sts = MFX_ERR_NONE;
964 }
965 if (!bLastCycle && (DecExtSurface.pSurface == NULL) )
966 {
967 m_pBSProcessor->ResetInput();
968
969 if (!GetNumFramesForReset())
970 SetNumFramesForReset(m_nProcessedFramesNum);
971 sts = MFX_ERR_NONE;
972 continue;
973 }
974 MSDK_BREAK_ON_ERROR(sts);
975 }
976
977 if (m_pmfxVPP.get() && !m_rawInput)
978 {
979 if (m_bIsFieldWeaving)
980 {
981 // We might have 2 cases: decoder gives us pairs (TF BF)... or (BF)(TF). In first case we should set TFF for output, in second - BFF.
982 // So, if even input surface is BF, we set TFF for output and vise versa. For odd input surface - no matter what we set.
983 if (!(m_nProcessedFramesNum % 2))
984 {
985 if (DecExtSurface.pSurface)
986 {
987 if ((DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF))
988 {
989 m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_BFF;
990 }
991 if (DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_BFF)
992 {
993 m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_TFF;
994 }
995 }
996 }
997 sts = VPPOneFrame(&DecExtSurface, &VppExtSurface);
998 }
999 else
1000 {
1001 if (m_bIsFieldSplitting)
1002 {
1003 if (DecExtSurface.pSurface)
1004 {
1005 if (DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF || DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_BFF)
1006 {
1007 m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_SINGLE;
1008 sts = VPPOneFrame(&DecExtSurface, &VppExtSurface);
1009 }
1010 else
1011 {
1012 VppExtSurface.pSurface = DecExtSurface.pSurface;
1013 VppExtSurface.pAuxCtrl = DecExtSurface.pAuxCtrl;
1014 VppExtSurface.Syncp = DecExtSurface.Syncp;
1015 }
1016 }
1017 else
1018 {
1019 sts = VPPOneFrame(&DecExtSurface, &VppExtSurface);
1020 }
1021 }
1022 else
1023 {
1024 sts = VPPOneFrame(&DecExtSurface, &VppExtSurface);
1025 }
1026 }
1027 // check for interlaced stream
1028 }
1029 else // no VPP - just copy pointers
1030 {
1031 VppExtSurface.pSurface = DecExtSurface.pSurface;
1032 VppExtSurface.Syncp = DecExtSurface.Syncp;
1033 }
1034
1035 //--- Sometimes VPP may return 2 surfaces on output, for the first one it'll return status MFX_ERR_MORE_SURFACE - we have to call VPPOneFrame again in this case
1036 if(MFX_ERR_MORE_SURFACE == sts)
1037 {
1038 shouldReadNextFrame=false;
1039 sts=MFX_ERR_NONE;
1040 }
1041 else
1042 {
1043 shouldReadNextFrame=true;
1044 }
1045
1046 if (sts == MFX_ERR_MORE_DATA || !VppExtSurface.pSurface)
1047 {
1048 if (!bEndOfFile )
1049 {
1050 sts = MFX_ERR_NONE;
1051 continue; // go get next frame from Decode
1052 }
1053 }
1054 if (sts == MFX_ERR_MORE_DATA && m_pmfxPreENC.get())
1055 {
1056 VppExtSurface.pSurface = NULL; // to get buffered VPP or ENC frames
1057 sts = MFX_ERR_NONE;
1058 }
1059
1060 MSDK_BREAK_ON_ERROR(sts);
1061
1062 if (m_pmfxPreENC.get())
1063 {
1064 sts = PreEncOneFrame(&VppExtSurface, &PreEncExtSurface);
1065 }
1066 else // no VPP - just copy pointers
1067 {
1068 PreEncExtSurface.pSurface = VppExtSurface.pSurface;
1069 PreEncExtSurface.Syncp = VppExtSurface.Syncp;
1070 }
1071
1072 if (sts == MFX_ERR_MORE_DATA || !PreEncExtSurface.pSurface)
1073 {
1074 if (!bEndOfFile )
1075 {
1076 sts = MFX_ERR_NONE;
1077 continue; // go get next frame from Decode
1078 }
1079 }
1080 if (!bLastCycle)
1081 {
1082 sts = MFX_ERR_NONE;
1083 }
1084 MSDK_BREAK_ON_ERROR(sts);
1085
1086 // If session is not joined and it is not parent - synchronize.
1087 // If there was PreENC plugin in the pipeline - synchronize, because
1088 // plugin will output data to the extended buffers and mediasdk can't
1089 // track such dependency on its own.
1090 if ((!m_bIsJoinSession && m_pParentPipeline) || m_pmfxPreENC.get())
1091 {
1092 MFX_ITT_TASK("SyncOperation");
1093 sts = m_pmfxSession->SyncOperation(PreEncExtSurface.Syncp, MSDK_WAIT_INTERVAL);
1094 HandlePossibleGpuHang(sts);
1095 PreEncExtSurface.Syncp = NULL;
1096 MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "PreEnc: SyncOperation failed");
1097 }
1098
1099 // add surfaces in queue for all sinks
1100 pNextBuffer->AddSurface(PreEncExtSurface);
1101 /* one of key parts for N_to_1 mode:
1102 * decoded frame should be in one buffer only as we have only 1 (one!) sink
1103 * */
1104 if (0 == m_nVPPCompEnable)
1105 {
1106 while (pNextBuffer->m_pNext)
1107 {
1108 pNextBuffer = pNextBuffer->m_pNext;
1109 pNextBuffer->AddSurface(PreEncExtSurface);
1110 }
1111 }
1112
1113 // We need to synchronize oldest stored surface if we've already stored enough surfaces in buffer (buffer length >= AsyncDepth)
1114 // Because we have to wait for decoder to finish processing and free some internally used surfaces
1115 //mfxU32 len = pNextBuffer->GetLength();
1116 if(pNextBuffer->GetLength()>=m_AsyncDepth)
1117 {
1118 ExtendedSurface frontSurface;
1119 pNextBuffer->GetSurface(frontSurface);
1120
1121 if(frontSurface.Syncp)
1122 {
1123 sts = m_pmfxSession->SyncOperation(frontSurface.Syncp, MSDK_WAIT_INTERVAL);
1124 HandlePossibleGpuHang(sts);
1125 MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "SyncOperation failed");
1126 frontSurface.Syncp=NULL;
1127 }
1128 }
1129
1130 if (!statisticsWindowSize && 0 == (m_nProcessedFramesNum - 1) % 100)
1131 {
1132 msdk_printf(MSDK_STRING("."));
1133 }
1134
1135 if (bEndOfFile && m_nTimeout)
1136 {
1137 break;
1138 }
1139
1140 msdk_tick nFrameTime = msdk_time_get_tick() - nBeginTime;
1141 if (nFrameTime < m_nReqFrameTime)
1142 {
1143 MSDK_USLEEP((mfxU32)(m_nReqFrameTime - nFrameTime));
1144 }
1145 if (++m_nProcessedFramesNum >= m_MaxFramesForTranscode)
1146 {
1147 break;
1148 }
1149 }
1150
1151 MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA);
1152
1153 NoMoreFramesSignal();
1154
1155 if (MFX_ERR_NONE == sts)
1156 sts = MFX_WRN_VALUE_NOT_CHANGED;
1157
1158 return sts;
1159 } // mfxStatus CTranscodingPipeline::Decode()
1160
Encode()1161 mfxStatus CTranscodingPipeline::Encode()
1162 {
1163 mfxStatus sts = MFX_ERR_NONE;
1164 ExtendedSurface DecExtSurface = {};
1165 ExtendedSurface VppExtSurface = {};
1166 ExtendedBS *pBS = NULL;
1167 bool isQuit = false;
1168 bool bPollFlag = false;
1169 int nFramesAlreadyPut = 0;
1170 SafetySurfaceBuffer *curBuffer = m_pBuffer;
1171
1172 bool shouldReadNextFrame=true;
1173 while (MFX_ERR_NONE == sts || MFX_ERR_MORE_DATA == sts)
1174 {
1175 msdk_tick nBeginTime = msdk_time_get_tick(); // microseconds
1176 if(shouldReadNextFrame)
1177 {
1178 if(isQuit)
1179 {
1180 // We're here because one of decoders has reported that there're no any more frames ready.
1181 //So, let's pass null surface to extract data from the VPP and encoder caches.
1182
1183 MSDK_ZERO_MEMORY(DecExtSurface);
1184 }
1185 else
1186 {
1187 // Getting next frame
1188 while (MFX_ERR_MORE_SURFACE == curBuffer->GetSurface(DecExtSurface))
1189 {
1190 if (MFX_ERR_NONE != curBuffer->WaitForSurfaceInsertion(MSDK_SURFACE_WAIT_INTERVAL)) {
1191 msdk_printf(MSDK_STRING("ERROR: timed out waiting surface from upstream component\n"));
1192 return MFX_ERR_NOT_FOUND;
1193 }
1194 }
1195 }
1196
1197 // if session is not joined and it is not parent - synchronize
1198 if (!m_bIsJoinSession && m_pParentPipeline)
1199 {
1200 // if it is not already synchronized
1201 if (DecExtSurface.Syncp)
1202 {
1203 MFX_ITT_TASK("SyncOperation");
1204 sts = m_pParentPipeline->m_pmfxSession->SyncOperation(DecExtSurface.Syncp, MSDK_WAIT_INTERVAL);
1205 HandlePossibleGpuHang(sts);
1206 MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "Encode: SyncOperation failed");
1207 }
1208 }
1209
1210 mfxU32 NumFramesForReset = m_pParentPipeline ? m_pParentPipeline->GetNumFramesForReset() : 0;
1211 if (NumFramesForReset && !(nFramesAlreadyPut % NumFramesForReset) )
1212 {
1213 m_bInsertIDR = true;
1214 }
1215
1216 if (NULL == DecExtSurface.pSurface)
1217 {
1218 isQuit = true;
1219 }
1220 }
1221
1222 if (m_pmfxVPP.get())
1223 {
1224 sts = VPPOneFrame(&DecExtSurface, &VppExtSurface);
1225 VppExtSurface.pAuxCtrl = DecExtSurface.pAuxCtrl;
1226 }
1227 else // no VPP - just copy pointers
1228 {
1229 VppExtSurface.pSurface = DecExtSurface.pSurface;
1230 VppExtSurface.pAuxCtrl = DecExtSurface.pAuxCtrl;
1231 VppExtSurface.Syncp = DecExtSurface.Syncp;
1232 }
1233
1234 if(MFX_ERR_MORE_SURFACE == sts)
1235 {
1236 shouldReadNextFrame=false;
1237 sts=MFX_ERR_NONE;
1238 }
1239 else
1240 {
1241 shouldReadNextFrame=true;
1242 }
1243
1244 if (MFX_ERR_MORE_DATA == sts)
1245 {
1246 if(isQuit)
1247 {
1248 // to get buffered VPP or ENC frames
1249 VppExtSurface.pSurface = NULL;
1250 sts = MFX_ERR_NONE;
1251 }
1252 else
1253 {
1254 curBuffer->ReleaseSurface(DecExtSurface.pSurface);
1255
1256 //--- We should switch to another buffer ONLY in case of Composition
1257 if (curBuffer->m_pNext != NULL && m_nVPPCompEnable > 0)
1258 {
1259 curBuffer = curBuffer->m_pNext;
1260 continue;
1261 }
1262 else
1263 {
1264 curBuffer = m_pBuffer;
1265 continue; /* No more buffer from decoders */
1266 }
1267 }
1268 }
1269
1270 MSDK_CHECK_STATUS(sts, "Unexpected error!!");
1271
1272 if (m_nVPPCompEnable > 0)
1273 curBuffer->ReleaseSurface(DecExtSurface.pSurface);
1274
1275 // Do RenderFrame before Encode to improves on-screen performance
1276 // Presentation packet would now precedes "ENC" packet within the EU
1277 if ((m_nVPPCompEnable == VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode))
1278 {
1279 if(VppExtSurface.pSurface)
1280 {
1281 // Sync to ensure VPP is completed to avoid flicker
1282 sts = m_pmfxSession->SyncOperation(VppExtSurface.Syncp, MSDK_WAIT_INTERVAL);
1283 HandlePossibleGpuHang(sts);
1284 MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "VPP: SyncOperation failed");
1285
1286 /* in case if enabled dumping into file for after VPP composition */
1287 if (DUMP_FILE_VPP_COMP == m_vppCompDumpRenderMode)
1288 {
1289 sts = DumpSurface2File(VppExtSurface.pSurface);
1290 MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
1291 }
1292 /* Rendering may be explicitly disabled for performance measurements */
1293 if (NULL_RENDER_VPP_COMP != m_vppCompDumpRenderMode)
1294 {
1295
1296 #if defined(_WIN32) || defined(_WIN64)
1297 sts = m_hwdev4Rendering->RenderFrame(VppExtSurface.pSurface, m_pMFXAllocator);
1298 #else
1299 sts = m_hwdev4Rendering->RenderFrame(VppExtSurface.pSurface, NULL);
1300 #endif
1301 MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
1302 } // if (NULL_RENDER_VPP_COMP != m_vppCompDumpRenderMode)
1303 }
1304 }
1305
1306 curBuffer = m_pBuffer;
1307
1308 pBS = m_pBSStore->GetNext();
1309 if (!pBS)
1310 return MFX_ERR_NOT_FOUND;
1311
1312 m_BSPool.push_back(pBS);
1313
1314 mfxU32 NumFramesForReset = m_pParentPipeline ? m_pParentPipeline->GetNumFramesForReset() : 0;
1315 if (NumFramesForReset && !(m_nProcessedFramesNum % NumFramesForReset))
1316 {
1317 m_pBSProcessor->ResetOutput();
1318 }
1319
1320 SetEncCtrlRT(VppExtSurface, m_bInsertIDR);
1321 m_bInsertIDR = false;
1322
1323 if ((m_nVPPCompEnable != VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode))
1324 {
1325 if(m_mfxEncParams.mfx.CodecId != MFX_CODEC_DUMP)
1326 {
1327 if (bPollFlag)
1328 {
1329 VppExtSurface.pSurface = 0;
1330 }
1331 sts = EncodeOneFrame(&VppExtSurface, &m_BSPool.back()->Bitstream);
1332
1333 // Count only real surfaces
1334 if (VppExtSurface.pSurface)
1335 {
1336 m_nProcessedFramesNum++;
1337 }
1338
1339 if (m_nProcessedFramesNum >= m_MaxFramesForTranscode)
1340 {
1341 bPollFlag = true;
1342 }
1343
1344 if (!sts)
1345 nFramesAlreadyPut++;
1346 }
1347 else
1348 {
1349 sts = Surface2BS(&VppExtSurface, &m_BSPool.back()->Bitstream, m_encoderFourCC);
1350 }
1351 }
1352
1353 if(shouldReadNextFrame) // Release current decoded surface only if we're going to read next one during next iteration
1354 {
1355 m_pBuffer->ReleaseSurface(DecExtSurface.pSurface);
1356 }
1357
1358 // check if we need one more frame from decode
1359 if (MFX_ERR_MORE_DATA == sts)
1360 {
1361 // the task in not in Encode queue
1362 m_BSPool.pop_back();
1363 m_pBSStore->Release(pBS);
1364
1365 if (NULL == VppExtSurface.pSurface ) // there are no more buffered frames in encoder
1366 {
1367 break;
1368 }
1369 else
1370 {
1371 // get next frame from Decode
1372 sts = MFX_ERR_NONE;
1373 continue;
1374 }
1375 }
1376
1377 // check encoding result
1378 MSDK_CHECK_STATUS(sts, "<EncodeOneFrame|Surface2BS> failed");
1379
1380 // output statistics if several conditions are true OR we've approached
1381 // the end, and statisticsWindowSize is not 0, but number of frames is
1382 // not multiple of statisticsWindowSize; should use m_nProcessedFramesNum
1383 // as it simplifies conditions
1384 if ( (statisticsWindowSize && m_nOutputFramesNum && 0 == m_nProcessedFramesNum % statisticsWindowSize) ||
1385 (statisticsWindowSize && (m_nProcessedFramesNum >= m_MaxFramesForTranscode)))
1386 {
1387 outputStatistics.PrintStatistics(GetPipelineID());
1388 outputStatistics.ResetStatistics();
1389 }
1390
1391 m_BSPool.back()->Syncp = VppExtSurface.Syncp;
1392 m_BSPool.back()->pCtrl = VppExtSurface.pAuxCtrl;
1393
1394 /* Actually rendering... if enabled
1395 * SYNC have not done by driver !!! */
1396 if ((m_nVPPCompEnable == VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode))
1397 {
1398 if(m_BSPool.size())
1399 {
1400 ExtendedBS *pBitstreamEx_temp = m_BSPool.front();
1401
1402 // get result coded stream
1403 ////Note! Better to do rendering before encode
1404 // if(VppExtSurface.pSurface)
1405 // {
1406 // if(m_nVPPCompEnable != VppCompOnlyEncode)
1407 // {
1408 // sts = m_pmfxSession->SyncOperation(VppExtSurface.Syncp, MSDK_WAIT_INTERVAL);
1409 // MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "VPP: SyncOperation failed");
1410 // }
1411 //#if defined(_WIN32) || defined(_WIN64)
1412 // sts = m_hwdev4Rendering->RenderFrame(VppExtSurface.pSurface, m_pMFXAllocator);
1413 //#else
1414 // sts = m_hwdev4Rendering->RenderFrame(VppExtSurface.pSurface, NULL);
1415 //#endif
1416 // MSDK_CHECK_STATUS(sts, "m_hwdev4Rendering->RenderFrame failed");
1417 // }
1418
1419 UnPreEncAuxBuffer(pBitstreamEx_temp->pCtrl);
1420
1421 if (m_nVPPCompEnable != VppCompOnlyEncode)
1422 {
1423 pBitstreamEx_temp->Bitstream.DataLength = 0;
1424 pBitstreamEx_temp->Bitstream.DataOffset = 0;
1425
1426 m_BSPool.pop_front();
1427 m_pBSStore->Release(pBitstreamEx_temp);
1428 }
1429 }
1430
1431 //--- If there's no data coming out from VPP and there's no data coming from decoders (isQuit==true),
1432 // then we should quit, otherwise we may stuck here forever (cause there's no new data coming)
1433 if(!VppExtSurface.pSurface && isQuit)
1434 {
1435 break;
1436 }
1437 }
1438
1439 if ((m_nVPPCompEnable != VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode))
1440 {
1441 if (m_BSPool.size() == m_AsyncDepth)
1442 {
1443 sts = PutBS();
1444 MSDK_CHECK_STATUS(sts, "PutBS failed");
1445 }
1446 else
1447 {
1448 continue;
1449 }
1450 } // if (m_nVPPCompEnable != VppCompOnly)
1451
1452 msdk_tick nFrameTime = msdk_time_get_tick() - nBeginTime;
1453 if (nFrameTime < m_nReqFrameTime)
1454 {
1455 MSDK_USLEEP((mfxU32)(m_nReqFrameTime - nFrameTime));
1456 }
1457 }
1458 MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA);
1459
1460 if (m_nVPPCompEnable != VppCompOnly || (m_nVPPCompEnable == VppCompOnlyEncode))
1461 {
1462 // need to get buffered bitstream
1463 if (MFX_ERR_NONE == sts)
1464 {
1465 while (m_BSPool.size())
1466 {
1467 sts = PutBS();
1468 MSDK_CHECK_STATUS(sts, "PutBS failed");
1469 }
1470 }
1471 }
1472
1473 // Clean up decoder buffers to avoid locking them (if some decoder still have some data to decode, but does not have enough surfaces)
1474 if(m_nVPPCompEnable!=0)
1475 {
1476 // Composition case - we have to clean up all buffers (all of them have data from decoders)
1477 for(SafetySurfaceBuffer * buf = m_pBuffer;buf!=NULL; buf=buf->m_pNext)
1478 {
1479 while (buf->GetSurface(DecExtSurface)!=MFX_ERR_MORE_SURFACE)
1480 {
1481 buf->ReleaseSurface(DecExtSurface.pSurface);
1482 buf->CancelBuffering();
1483 }
1484 }
1485 }
1486 else
1487 {
1488 // Clean up only current buffer
1489 m_pBuffer->CancelBuffering();
1490 while (m_pBuffer->GetSurface(DecExtSurface)!=MFX_ERR_MORE_SURFACE)
1491 {
1492 m_pBuffer->ReleaseSurface(DecExtSurface.pSurface);
1493 }
1494 }
1495
1496 // Close encoder and decoder and clean up buffers
1497 if (m_pmfxENC.get())
1498 m_pmfxENC->Close();
1499
1500 if (m_pmfxVPP.get())
1501 m_pmfxVPP->Close();
1502
1503
1504 if (MFX_ERR_NONE == sts)
1505 sts = MFX_WRN_VALUE_NOT_CHANGED;
1506 return sts;
1507
1508 } // mfxStatus CTranscodingPipeline::Encode()
1509
1510 #if MFX_VERSION >= 1022
FillMBQPBuffer(mfxExtMBQP & qpMap,mfxU16 pictStruct)1511 void CTranscodingPipeline::FillMBQPBuffer(mfxExtMBQP &qpMap, mfxU16 pictStruct)
1512 {
1513 // External MBQP case
1514 if (m_bExtMBQP)
1515 {
1516 // Use simplistic approach to fill in QP buffer
1517 for (size_t i = 0; i < qpMap.NumQPAlloc; i++)
1518 {
1519 qpMap.QP[i] = i % 52;
1520 }
1521 return;
1522 }
1523
1524 // External MBQP with ROI case
1525 if (pictStruct == MFX_PICSTRUCT_PROGRESSIVE)
1526 {
1527 mfxI8 fQP = (m_nSubmittedFramesNum % m_GOPSize) ? (mfxI8)m_QPforP : (mfxI8)m_QPforI;
1528 std::memset(qpMap.QP, fQP, qpMap.NumQPAlloc);
1529
1530 // printf("QP expectation: %d, map PTR %lld\n",fQP,(long long int)qpMap.QP);
1531
1532 if (m_ROIData.size() > m_nSubmittedFramesNum)
1533 {
1534 mfxExtEncoderROI &roi = m_ROIData[m_nSubmittedFramesNum];
1535 for (mfxI32 i=roi.NumROI-1; i>=0; i--)
1536 {
1537 mfxU32 l = (roi.ROI[i].Left) >> 4,
1538 t = (roi.ROI[i].Top) >> 4,
1539 r = (roi.ROI[i].Right + 15) >> 4,
1540 b = (roi.ROI[i].Bottom + 15) >> 4;
1541
1542 //Additional 32x32 block alignment for HEVC
1543 if(m_mfxEncParams.mfx.CodecId == MFX_CODEC_HEVC)
1544 {
1545 l = ((roi.ROI[i].Left) >> 5) << 1;
1546 t = ((roi.ROI[i].Top) >> 5) << 1;
1547 r = ((roi.ROI[i].Right + 31) >> 5) << 1;
1548 b = ((roi.ROI[i].Bottom + 31) >> 5) << 1;
1549 }
1550
1551 if(l > m_QPmapWidth) l = m_QPmapWidth;
1552 if(r > m_QPmapWidth) r = m_QPmapWidth;
1553 if(t > m_QPmapHeight) t = m_QPmapHeight;
1554 if(b > m_QPmapHeight) b = m_QPmapHeight;
1555
1556 mfxI8 qp_value = (mfxI8)std::min(std::max(fQP + (mfxI8)roi.ROI[i].DeltaQP, 0), 51);
1557
1558 for (mfxU32 k=t; k<b; k++)
1559 std::memset(qpMap.QP + k*m_QPmapWidth + l, qp_value, r-l);
1560 }
1561 }
1562 }
1563 else if (pictStruct == MFX_PICSTRUCT_FIELD_TFF || pictStruct == MFX_PICSTRUCT_FIELD_BFF)
1564 {
1565 mfxU32 fQP[2] = {(m_nSubmittedFramesNum % m_GOPSize) ? m_QPforP : m_QPforI,
1566 (m_GOPSize > 1) ? m_QPforP : m_QPforI};
1567 mfxU32 fIdx[2] = {2*m_nSubmittedFramesNum, 2*m_nSubmittedFramesNum+1};
1568 mfxU32 fOff[2] = {0, 0};
1569
1570 fOff[(pictStruct == MFX_PICSTRUCT_FIELD_BFF) ? 0 : 1] = qpMap.NumQPAlloc/2;
1571
1572 for (int fld=0; fld<=1; fld++)
1573 {
1574 std::memset(qpMap.QP + fOff[fld], fQP[fld], qpMap.NumQPAlloc/2);
1575 if (m_ROIData.size() > fIdx[fld])
1576 {
1577 mfxExtEncoderROI &roi = m_ROIData[fIdx[fld]];
1578 for (mfxI32 i=roi.NumROI-1; i>=0; i--)
1579 {
1580 mfxU32 l = (roi.ROI[i].Left) >> 4,
1581 t = (roi.ROI[i].Top) >> 5,
1582 r = (roi.ROI[i].Right + 15) >> 4,
1583 b = (roi.ROI[i].Bottom + 31) >> 5;
1584 mfxI8 qp_delta = (mfxI8)roi.ROI[i].DeltaQP;
1585 mfxU8 roi_qp = (mfxU8)std::min(std::max(mfxI8(fQP[fld]) + qp_delta, 0), 51);
1586
1587 if(l > m_QPmapWidth) l = m_QPmapWidth;
1588 if(r > m_QPmapWidth) r = m_QPmapWidth;
1589 if(t > m_QPmapHeight/2) t = m_QPmapHeight/2;
1590 if(b > m_QPmapHeight/2) b = m_QPmapHeight/2;
1591
1592 for (mfxU32 k=t; k<b; k++)
1593 std::memset(qpMap.QP + fOff[fld] + k*m_QPmapWidth + l, roi_qp, r-l);
1594 }
1595 }
1596 }
1597 }
1598 else
1599 {
1600 mfxI8 fQP = (m_nSubmittedFramesNum % m_GOPSize) ? (mfxI8)m_QPforP : (mfxI8)m_QPforI;
1601 std::memset(qpMap.QP, fQP, qpMap.NumQPAlloc);
1602 }
1603 }
1604 #endif //MFX_VERSION >= 1022
1605
SetEncCtrlRT(ExtendedSurface & extSurface,bool bInsertIDR)1606 void CTranscodingPipeline::SetEncCtrlRT(ExtendedSurface& extSurface, bool bInsertIDR)
1607 {
1608 extSurface.pEncCtrl = NULL;
1609 if (extSurface.pAuxCtrl) {
1610 extSurface.pEncCtrl = &extSurface.pAuxCtrl->encCtrl;
1611 }
1612
1613 #if MFX_VERSION >= 1022
1614
1615 if (extSurface.pSurface) {
1616 void* keyId = (void*)extSurface.pSurface;
1617
1618 // Use encoded surface pointer to find placeholders for run-time structures in maps
1619 if (m_bUseQPMap && m_bufExtMBQP.find(keyId) == m_bufExtMBQP.end()) {
1620 m_extBuffPtrStorage[keyId] = std::vector<mfxExtBuffer*>();
1621
1622 m_qpMapStorage[keyId] = std::vector<mfxU8>();
1623 m_qpMapStorage[keyId].resize(m_QPmapWidth*m_QPmapHeight);
1624
1625 m_bufExtMBQP[keyId] = mfxExtMBQP();
1626 m_bufExtMBQP[keyId].Header.BufferId = MFX_EXTBUFF_MBQP;
1627 m_bufExtMBQP[keyId].Header.BufferSz = sizeof(mfxExtMBQP);
1628 m_bufExtMBQP[keyId].NumQPAlloc = m_QPmapWidth*m_QPmapHeight;
1629 m_bufExtMBQP[keyId].QP = m_QPmapWidth && m_QPmapHeight ? &(m_qpMapStorage[keyId][0]) : NULL;
1630 }
1631
1632 // Initialize *pCtrl optionally copying content of the pExtSurface.pAuxCtrl.encCtrl
1633 mfxEncodeCtrl& ctrl = encControlStorage[keyId];
1634 MSDK_ZERO_MEMORY(ctrl);
1635
1636 if (extSurface.pEncCtrl) {
1637 ctrl = *extSurface.pEncCtrl;
1638 }
1639
1640 // Copy all extended buffer pointers from pExtSurface.pAuxCtrl.encCtrl
1641 m_extBuffPtrStorage[keyId].clear();
1642 if (extSurface.pAuxCtrl) {
1643 for (unsigned int i = 0; i < ctrl.NumExtParam; i++) {
1644 m_extBuffPtrStorage[keyId].push_back(extSurface.pAuxCtrl->encCtrl.ExtParam[i]);
1645 }
1646 }
1647
1648 // Attach additional buffer with either MBQP or ROI information
1649 if (m_bUseQPMap) {
1650 #if (MFX_VERSION >= 1022)
1651 FillMBQPBuffer(m_bufExtMBQP[keyId], extSurface.pSurface->Info.PicStruct);
1652 m_extBuffPtrStorage[keyId].push_back((mfxExtBuffer *)&m_bufExtMBQP[keyId]);
1653 #endif
1654 } else {
1655 if (m_ROIData.size() > m_nSubmittedFramesNum)
1656 m_extBuffPtrStorage[keyId].push_back((mfxExtBuffer *)&m_ROIData[m_nSubmittedFramesNum]);
1657 }
1658
1659 // Replace the buffers pointer to pre-allocated storage
1660 ctrl.NumExtParam = (mfxU16)m_extBuffPtrStorage[keyId].size();
1661 if (ctrl.NumExtParam) {
1662 ctrl.ExtParam = &(m_extBuffPtrStorage[keyId][0]);
1663 }
1664
1665 extSurface.pEncCtrl = &ctrl;
1666 m_nSubmittedFramesNum++;
1667 }
1668 #endif //MFX_VERSION >= 1022
1669
1670 if (bInsertIDR && extSurface.pSurface)
1671 {
1672 if (extSurface.pEncCtrl == NULL)
1673 {
1674 mfxEncodeCtrl& ctrl = encControlStorage[(void*)extSurface.pSurface];
1675 MSDK_ZERO_MEMORY(ctrl);
1676 extSurface.pEncCtrl = &ctrl;
1677 }
1678 extSurface.pEncCtrl->FrameType = MFX_FRAMETYPE_I | MFX_FRAMETYPE_IDR | MFX_FRAMETYPE_REF;
1679 }
1680 else
1681 {
1682 if (extSurface.pEncCtrl)
1683 {
1684 extSurface.pEncCtrl->FrameType = 0;
1685 }
1686 }
1687 }
1688
Transcode()1689 mfxStatus CTranscodingPipeline::Transcode()
1690 {
1691 mfxStatus sts = MFX_ERR_NONE;
1692 ExtendedSurface DecExtSurface = {0};
1693 ExtendedSurface VppExtSurface = {0};
1694 ExtendedBS *pBS = NULL;
1695 bool bNeedDecodedFrames = true; // indicates if we need to decode frames
1696 bool bEndOfFile = false;
1697 bool bLastCycle = false;
1698 bool shouldReadNextFrame=true;
1699
1700 time_t start = time(0);
1701 while (MFX_ERR_NONE == sts )
1702 {
1703 msdk_tick nBeginTime = msdk_time_get_tick(); // microseconds.
1704
1705 if (time(0) - start >= m_nTimeout)
1706 bLastCycle = true;
1707 if (m_MaxFramesForTranscode == m_nProcessedFramesNum)
1708 {
1709 DecExtSurface.pSurface = NULL; // to get buffered VPP or ENC frames
1710 bNeedDecodedFrames = false; // no more decoded frames needed
1711 }
1712
1713 // if need more decoded frames
1714 // decode a frame
1715 if (bNeedDecodedFrames && shouldReadNextFrame)
1716 {
1717 if (!bEndOfFile)
1718 {
1719 sts = DecodeOneFrame(&DecExtSurface);
1720 if (MFX_ERR_MORE_DATA == sts)
1721 {
1722 if (!bLastCycle)
1723 {
1724 m_bInsertIDR = true;
1725
1726 m_pBSProcessor->ResetInput();
1727 m_pBSProcessor->ResetOutput();
1728 bNeedDecodedFrames = true;
1729
1730 bEndOfFile = false;
1731 sts = MFX_ERR_NONE;
1732 continue;
1733 }
1734 else
1735 {
1736 bEndOfFile = true;
1737 }
1738 }
1739 }
1740
1741 if (bEndOfFile)
1742 {
1743 sts = DecodeLastFrame(&DecExtSurface);
1744 }
1745
1746 if (sts == MFX_ERR_MORE_DATA)
1747 {
1748 DecExtSurface.pSurface = NULL; // to get buffered VPP or ENC frames
1749 sts = MFX_ERR_NONE;
1750 }
1751 MSDK_CHECK_STATUS(sts, "Decode<One|Last>Frame failed");
1752 }
1753 if (m_bIsFieldWeaving && DecExtSurface.pSurface != NULL)
1754 {
1755 m_mfxDecParams.mfx.FrameInfo.PicStruct = DecExtSurface.pSurface->Info.PicStruct;
1756 }
1757 if (m_bIsFieldSplitting && DecExtSurface.pSurface != NULL)
1758 {
1759 m_mfxDecParams.mfx.FrameInfo.PicStruct = DecExtSurface.pSurface->Info.PicStruct;
1760 }
1761 // pre-process a frame
1762 if (m_pmfxVPP.get() && bNeedDecodedFrames && !m_rawInput)
1763 {
1764 if (m_bIsFieldWeaving)
1765 {
1766 // In case of field weaving output surface's parameters for ODD calls to VPPOneFrame will be ignored (because VPP will return ERR_MORE_DATA).
1767 // So, we need to set output surface picstruct properly for EVEN calls (no matter what will be set for ODD calls).
1768 // We might have 2 cases: decoder gives us pairs (TF BF)... or (BF)(TF). In first case we should set TFF for output, in second - BFF.
1769 // So, if even input surface is BF, we set TFF for output and vise versa. For odd input surface - no matter what we set.
1770 if (DecExtSurface.pSurface)
1771 {
1772 if ((DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF)) // Incoming Top Field in a single surface
1773 {
1774 m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_BFF;
1775 }
1776 if (DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_BFF) // Incoming Bottom Field in a single surface
1777 {
1778 m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_TFF;
1779 }
1780 }
1781 sts = VPPOneFrame(&DecExtSurface, &VppExtSurface);
1782 }
1783 else
1784 {
1785 if (m_bIsFieldSplitting)
1786 {
1787 if (DecExtSurface.pSurface)
1788 {
1789 if (DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF || DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_BFF)
1790 {
1791 m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_SINGLE;
1792 sts = VPPOneFrame(&DecExtSurface, &VppExtSurface);
1793 }
1794 else
1795 {
1796 VppExtSurface.pSurface = DecExtSurface.pSurface;
1797 VppExtSurface.pAuxCtrl = DecExtSurface.pAuxCtrl;
1798 VppExtSurface.Syncp = DecExtSurface.Syncp;
1799 }
1800 }
1801 else
1802 {
1803 sts = VPPOneFrame(&DecExtSurface, &VppExtSurface);
1804 }
1805 }
1806 else
1807 {
1808 sts = VPPOneFrame(&DecExtSurface, &VppExtSurface);
1809 }
1810 }
1811 // check for interlaced stream
1812 }
1813 else // no VPP - just copy pointers
1814 {
1815 VppExtSurface.pSurface = DecExtSurface.pSurface;
1816 VppExtSurface.pAuxCtrl = DecExtSurface.pAuxCtrl;
1817 VppExtSurface.Syncp = DecExtSurface.Syncp;
1818 }
1819
1820 if(MFX_ERR_MORE_SURFACE == sts)
1821 {
1822 shouldReadNextFrame=false;
1823 sts=MFX_ERR_NONE;
1824 }
1825 else
1826 {
1827 shouldReadNextFrame=true;
1828 }
1829
1830 if (sts == MFX_ERR_MORE_DATA)
1831 {
1832 sts = MFX_ERR_NONE;
1833 if (NULL == DecExtSurface.pSurface) // there are no more buffered frames in VPP
1834 {
1835 VppExtSurface.pSurface = NULL; // to get buffered ENC frames
1836 }
1837 else
1838 {
1839 continue; // go get next frame from Decode
1840 }
1841 }
1842
1843 MSDK_CHECK_STATUS(sts, "Unexpected error!!");
1844
1845 // encode frame
1846 pBS = m_pBSStore->GetNext();
1847 if (!pBS)
1848 return MFX_ERR_NOT_FOUND;
1849
1850 m_BSPool.push_back(pBS);
1851
1852 // Set Encoding control if it is required.
1853
1854 SetEncCtrlRT(VppExtSurface, m_bInsertIDR);
1855 m_bInsertIDR = false;
1856
1857 if (DecExtSurface.pSurface)
1858 m_nProcessedFramesNum++;
1859
1860 if(m_mfxEncParams.mfx.CodecId != MFX_CODEC_DUMP)
1861 {
1862 sts = EncodeOneFrame(&VppExtSurface, &m_BSPool.back()->Bitstream);
1863 }
1864 else
1865 {
1866
1867 sts = Surface2BS(&VppExtSurface, &m_BSPool.back()->Bitstream, m_encoderFourCC);
1868 }
1869
1870 // check if we need one more frame from decode
1871 if (MFX_ERR_MORE_DATA == sts)
1872 {
1873 // the task in not in Encode queue
1874 m_BSPool.pop_back();
1875 m_pBSStore->Release(pBS);
1876
1877 if (NULL == VppExtSurface.pSurface) // there are no more buffered frames in encoder
1878 {
1879 break;
1880 }
1881 sts = MFX_ERR_NONE;
1882 continue;
1883 }
1884
1885 // check encoding result
1886 MSDK_CHECK_STATUS(sts, "<EncodeOneFrame|Surface2BS> failed");
1887
1888 if(statisticsWindowSize)
1889 {
1890 if ( (statisticsWindowSize && m_nOutputFramesNum && 0 == m_nProcessedFramesNum % statisticsWindowSize) ||
1891 (statisticsWindowSize && (m_nProcessedFramesNum >= m_MaxFramesForTranscode)))
1892 {
1893 inputStatistics.PrintStatistics(GetPipelineID());
1894 outputStatistics.PrintStatistics(
1895 GetPipelineID(),
1896 (m_mfxEncParams.mfx.FrameInfo.FrameRateExtD)?
1897 (mfxF64)m_mfxEncParams.mfx.FrameInfo.FrameRateExtN/(mfxF64)m_mfxEncParams.mfx.FrameInfo.FrameRateExtD: -1);
1898 inputStatistics.ResetStatistics();
1899 outputStatistics.ResetStatistics();
1900 }
1901 }
1902 else if (0 == (m_nProcessedFramesNum - 1) % 100)
1903 {
1904 msdk_printf(MSDK_STRING("."));
1905 }
1906
1907 m_BSPool.back()->Syncp = VppExtSurface.Syncp;
1908
1909 if (m_BSPool.size() == m_AsyncDepth)
1910 {
1911 sts = PutBS();
1912 MSDK_CHECK_STATUS(sts, "PutBS failed");
1913 }
1914
1915 msdk_tick nFrameTime = msdk_time_get_tick() - nBeginTime;
1916 if (nFrameTime < m_nReqFrameTime)
1917 {
1918 MSDK_USLEEP((mfxU32)(m_nReqFrameTime - nFrameTime));
1919 }
1920 }
1921 MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA);
1922
1923 // need to get buffered bitstream
1924 if (MFX_ERR_NONE == sts)
1925 {
1926 while(m_BSPool.size())
1927 {
1928 sts = PutBS();
1929 MSDK_CHECK_STATUS(sts, "PutBS failed");
1930 }
1931 }
1932
1933 if (MFX_ERR_NONE == sts)
1934 sts = MFX_WRN_VALUE_NOT_CHANGED;
1935
1936 return sts;
1937 } // mfxStatus CTranscodingPipeline::Transcode()
1938
PutBS()1939 mfxStatus CTranscodingPipeline::PutBS()
1940 {
1941 mfxStatus sts = MFX_ERR_NONE;
1942 ExtendedBS *pBitstreamEx = m_BSPool.front();
1943 MSDK_CHECK_POINTER(pBitstreamEx, MFX_ERR_NULL_PTR);
1944
1945 // get result coded stream, synchronize only if we still have sync point
1946 if(pBitstreamEx->Syncp)
1947 {
1948 sts = m_pmfxSession->SyncOperation(pBitstreamEx->Syncp, MSDK_WAIT_INTERVAL);
1949 HandlePossibleGpuHang(sts);
1950 MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "Encode: SyncOperation failed");
1951 }
1952
1953 m_nOutputFramesNum++;
1954
1955 //--- Time measurements
1956 if (statisticsWindowSize)
1957 {
1958 outputStatistics.StopTimeMeasurementWithCheck();
1959 outputStatistics.StartTimeMeasurement();
1960 }
1961
1962 sts = m_pBSProcessor->ProcessOutputBitstream(&pBitstreamEx->Bitstream);
1963 MSDK_CHECK_STATUS(sts, "m_pBSProcessor->ProcessOutputBitstream failed");
1964
1965 UnPreEncAuxBuffer(pBitstreamEx->pCtrl);
1966
1967 pBitstreamEx->Bitstream.DataLength = 0;
1968 pBitstreamEx->Bitstream.DataOffset = 0;
1969
1970 if (m_BSPool.size())
1971 m_BSPool.pop_front();
1972 m_pBSStore->Release(pBitstreamEx);
1973
1974 return sts;
1975 } //mfxStatus CTranscodingPipeline::PutBS()
1976
DumpSurface2File(mfxFrameSurface1 * pSurf)1977 mfxStatus CTranscodingPipeline::DumpSurface2File(mfxFrameSurface1* pSurf)
1978 {
1979 mfxStatus sts = MFX_ERR_NONE;
1980 sts = m_pMFXAllocator->Lock(m_pMFXAllocator->pthis,pSurf->Data.MemId,&pSurf->Data);
1981 MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->Lock failed");
1982
1983 sts = m_dumpVppCompFileWriter.WriteNextFrame(pSurf);
1984 MSDK_CHECK_STATUS(sts, "m_dumpVppCompFileWriter.WriteNextFrame failed");
1985
1986 sts = m_pMFXAllocator->Unlock(m_pMFXAllocator->pthis,pSurf->Data.MemId,&pSurf->Data);
1987 MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->Unlock failed");
1988
1989 return sts;
1990 } // mfxStatus CTranscodingPipeline::DumpSurface2File(ExtendedSurface* pSurf)
1991
1992
Surface2BS(ExtendedSurface * pSurf,mfxBitstreamWrapper * pBS,mfxU32 fourCC)1993 mfxStatus CTranscodingPipeline::Surface2BS(ExtendedSurface* pSurf,mfxBitstreamWrapper* pBS, mfxU32 fourCC)
1994 {
1995 mfxStatus sts = MFX_ERR_MORE_DATA;
1996 // get result coded stream
1997 if (!pSurf->pSurface)
1998 {
1999 return MFX_ERR_MORE_DATA;
2000 }
2001
2002 if (pSurf->Syncp)
2003 {
2004 sts = m_pmfxSession->SyncOperation(pSurf->Syncp, MSDK_WAIT_INTERVAL);
2005 HandlePossibleGpuHang(sts);
2006 MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "SyncOperation failed");
2007 pSurf->Syncp = 0;
2008
2009 if (!m_pBSProcessor->IsNulOutput())
2010 {
2011 //--- Copying data from surface to bitstream
2012 sts = m_pMFXAllocator->Lock(m_pMFXAllocator->pthis, pSurf->pSurface->Data.MemId, &pSurf->pSurface->Data);
2013 MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->Lock failed");
2014
2015 switch(fourCC)
2016 {
2017 case 0: // Default value is MFX_FOURCC_I420
2018 case MFX_FOURCC_I420:
2019 sts = NV12asI420toBS(pSurf->pSurface, pBS);
2020 break;
2021 case MFX_FOURCC_NV12:
2022 sts=NV12toBS(pSurf->pSurface, pBS);
2023 break;
2024 case MFX_FOURCC_RGB4:
2025 sts=RGB4toBS(pSurf->pSurface, pBS);
2026 break;
2027 case MFX_FOURCC_YUY2:
2028 sts=YUY2toBS(pSurf->pSurface, pBS);
2029 break;
2030 }
2031 MSDK_CHECK_STATUS(sts, "<FourCC>toBS failed");
2032
2033 sts = m_pMFXAllocator->Unlock(m_pMFXAllocator->pthis, pSurf->pSurface->Data.MemId, &pSurf->pSurface->Data);
2034 MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->Unlock failed");
2035 }
2036 }
2037
2038 return sts;
2039 }
2040
NV12asI420toBS(mfxFrameSurface1 * pSurface,mfxBitstreamWrapper * pBS)2041 mfxStatus CTranscodingPipeline::NV12asI420toBS(mfxFrameSurface1* pSurface, mfxBitstreamWrapper* pBS)
2042 {
2043 mfxFrameInfo& info = pSurface->Info;
2044 mfxFrameData& data = pSurface->Data;
2045 if ((int)pBS->MaxLength - (int)pBS->DataLength < (int)(info.CropH*info.CropW * 3 / 2))
2046 {
2047 pBS->Extend(pBS->DataLength + (int)(info.CropH*info.CropW * 3 / 2));
2048 }
2049
2050 for (mfxU16 i = 0; i < info.CropH; i++)
2051 {
2052 MSDK_MEMCPY(pBS->Data + pBS->DataLength, data.Y + (info.CropY * data.Pitch + info.CropX) + i * data.Pitch, info.CropW);
2053 pBS->DataLength += info.CropW;
2054 }
2055
2056 mfxU16 h = info.CropH / 2;
2057 mfxU16 w = info.CropW;
2058
2059 for (mfxU16 offset = 0; offset<2; offset++)
2060 {
2061 for (mfxU16 i = 0; i < h; i++)
2062 {
2063 for (mfxU16 j = offset; j < w; j += 2)
2064 {
2065 pBS->Data[pBS->DataLength] = *(data.UV + (info.CropY * data.Pitch / 2 + info.CropX) + i * data.Pitch + j);
2066 pBS->DataLength++;
2067 }
2068 }
2069 }
2070
2071 return MFX_ERR_NONE;
2072 }
2073
NV12toBS(mfxFrameSurface1 * pSurface,mfxBitstreamWrapper * pBS)2074 mfxStatus CTranscodingPipeline::NV12toBS(mfxFrameSurface1* pSurface,mfxBitstreamWrapper* pBS)
2075 {
2076 mfxFrameInfo& info = pSurface->Info;
2077 mfxFrameData& data = pSurface->Data;
2078 if ((int)pBS->MaxLength-(int)pBS->DataLength < (int)(info.CropH*info.CropW*3/2))
2079 {
2080 pBS->Extend(pBS->DataLength+(int)(info.CropH*info.CropW*3/2));
2081 }
2082
2083 for (mfxU16 i = 0; i < info.CropH; i++)
2084 {
2085 MSDK_MEMCPY(pBS->Data+pBS->DataLength, data.Y + (info.CropY * data.Pitch + info.CropX)+ i * data.Pitch, info.CropW);
2086 pBS->DataLength += info.CropW;
2087 }
2088
2089 for(mfxU16 i = 0; i < info.CropH / 2;i++)
2090 {
2091 MSDK_MEMCPY(pBS->Data + pBS->DataLength, data.UV + (info.CropY * data.Pitch + info.CropX) + i * data.Pitch, info.CropW);
2092 pBS->DataLength += info.CropW;
2093 }
2094
2095 return MFX_ERR_NONE;
2096 }
2097
RGB4toBS(mfxFrameSurface1 * pSurface,mfxBitstreamWrapper * pBS)2098 mfxStatus CTranscodingPipeline::RGB4toBS(mfxFrameSurface1* pSurface,mfxBitstreamWrapper* pBS)
2099 {
2100 mfxFrameInfo& info = pSurface->Info;
2101 mfxFrameData& data = pSurface->Data;
2102 if( (int)pBS->MaxLength-(int)pBS->DataLength < (int)(info.CropH*info.CropW*4))
2103 {
2104 pBS->Extend(pBS->DataLength+(int)(info.CropH*info.CropW*4));
2105 }
2106
2107 for (mfxU16 i = 0; i < info.CropH; i++)
2108 {
2109 MSDK_MEMCPY(pBS->Data+pBS->DataLength, data.B + (info.CropY * data.Pitch + info.CropX*4)+ i * data.Pitch, info.CropW*4);
2110 pBS->DataLength += info.CropW*4;
2111 }
2112
2113 return MFX_ERR_NONE;
2114 }
2115
YUY2toBS(mfxFrameSurface1 * pSurface,mfxBitstreamWrapper * pBS)2116 mfxStatus CTranscodingPipeline::YUY2toBS(mfxFrameSurface1* pSurface,mfxBitstreamWrapper* pBS)
2117 {
2118 mfxFrameInfo& info = pSurface->Info;
2119 mfxFrameData& data = pSurface->Data;
2120 if((int)pBS->MaxLength-(int)pBS->DataLength < (int)(info.CropH*info.CropW*4))
2121 {
2122 pBS->Extend(pBS->DataLength+(int)(info.CropH*info.CropW*4));
2123 }
2124
2125 for (mfxU16 i = 0; i < info.CropH; i++)
2126 {
2127 MSDK_MEMCPY(pBS->Data+pBS->DataLength, data.Y + (info.CropY * data.Pitch + info.CropX/2*4)+ i * data.Pitch, info.CropW*2);
2128 pBS->DataLength += info.CropW*2;
2129 }
2130
2131 return MFX_ERR_NONE;
2132 }
2133
2134
AllocMVCSeqDesc()2135 mfxStatus CTranscodingPipeline::AllocMVCSeqDesc()
2136 {
2137 auto mvc = m_mfxDecParams.AddExtBuffer<mfxExtMVCSeqDesc>();
2138 mvc->View = new mfxMVCViewDependency[mvc->NumView];
2139 mvc->NumViewAlloc = mvc->NumView;
2140
2141 mvc->ViewId = new mfxU16[mvc->NumViewId];
2142 mvc->NumViewIdAlloc = mvc->NumViewId;
2143
2144 mvc->OP = new mfxMVCOperationPoint[mvc->NumOP];
2145 mvc->NumOPAlloc = mvc->NumOP;
2146
2147 return MFX_ERR_NONE;
2148 }
2149
FreeMVCSeqDesc()2150 void CTranscodingPipeline::FreeMVCSeqDesc()
2151 {
2152 mfxExtMVCSeqDesc* mvc = m_mfxDecParams;
2153 if (m_bOwnMVCSeqDescMemory && mvc)
2154 {
2155 MSDK_SAFE_DELETE_ARRAY(mvc->View);
2156 MSDK_SAFE_DELETE_ARRAY(mvc->ViewId);
2157 MSDK_SAFE_DELETE_ARRAY(mvc->OP);
2158 }
2159 }
2160
InitDecMfxParams(sInputParams * pInParams)2161 mfxStatus CTranscodingPipeline::InitDecMfxParams(sInputParams *pInParams)
2162 {
2163 mfxStatus sts = MFX_ERR_NONE;
2164 MSDK_CHECK_POINTER(pInParams, MFX_ERR_NULL_PTR);
2165
2166 m_mfxDecParams.AsyncDepth = m_AsyncDepth;
2167
2168 // configure and attach external parameters
2169 if (m_bUseOpaqueMemory)
2170 m_mfxDecParams.AddExtBuffer<mfxExtOpaqueSurfaceAlloc>();
2171
2172 if (pInParams->bIsMVC)
2173 m_mfxDecParams.AddExtBuffer<mfxExtMVCSeqDesc>();
2174
2175 if (!m_bUseOverlay)
2176 {
2177 // read a portion of data for DecodeHeader function
2178 sts = m_pBSProcessor->GetInputBitstream(&m_pmfxBS);
2179 if (MFX_ERR_MORE_DATA == sts)
2180 return sts;
2181 else
2182 MSDK_CHECK_STATUS(sts, "m_pBSProcessor->GetInputBitstream failed");
2183
2184 // try to find a sequence header in the stream
2185 // if header is not found this function exits with error (e.g. if device was lost and there's no header in the remaining stream)
2186 for (;;)
2187 {
2188 // trying to find PicStruct information in AVI headers
2189 if (pInParams->DecodeId == MFX_CODEC_JPEG)
2190 MJPEG_AVI_ParsePicStruct(m_pmfxBS);
2191
2192 // parse bit stream and fill mfx params
2193 sts = m_pmfxDEC->DecodeHeader(m_pmfxBS, &m_mfxDecParams);
2194
2195 if (MFX_ERR_MORE_DATA == sts)
2196 {
2197 if (m_pmfxBS->MaxLength == m_pmfxBS->DataLength)
2198 {
2199 m_pmfxBS->Extend(m_pmfxBS->MaxLength * 2);
2200 }
2201
2202 // read a portion of data for DecodeHeader function
2203 sts = m_pBSProcessor->GetInputBitstream(&m_pmfxBS);
2204 if (MFX_ERR_MORE_DATA == sts)
2205 return sts;
2206 else
2207 MSDK_CHECK_STATUS(sts, "m_pBSProcessor->GetInputBitstream failed");
2208
2209
2210 continue;
2211 }
2212 else if (MFX_ERR_NOT_ENOUGH_BUFFER == sts && pInParams->bIsMVC)
2213 {
2214 sts = AllocMVCSeqDesc();
2215 MSDK_CHECK_STATUS(sts, "m_pmfxDEC->DecodeHeader failed");
2216
2217 continue;
2218 }
2219 else
2220 break;
2221 }
2222
2223 // to enable decorative flags, has effect with 1.3 API libraries only
2224 // (in case of JPEG decoder - it is not valid to use this field)
2225 if (m_mfxDecParams.mfx.CodecId != MFX_CODEC_JPEG)
2226 m_mfxDecParams.mfx.ExtendedPicStruct = 1;
2227
2228 // check DecodeHeader status
2229 if (MFX_WRN_PARTIAL_ACCELERATION == sts)
2230 {
2231 msdk_printf(MSDK_STRING("WARNING: partial acceleration\n"));
2232 MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
2233 }
2234 MSDK_CHECK_STATUS(sts, "m_pmfxDEC->DecodeHeader failed");
2235
2236 // if input is interlaced JPEG stream
2237 if (((pInParams->DecodeId == MFX_CODEC_JPEG) && (m_pmfxBS->PicStruct == MFX_PICSTRUCT_FIELD_TFF))
2238 || (m_pmfxBS->PicStruct == MFX_PICSTRUCT_FIELD_BFF))
2239 {
2240 m_mfxDecParams.mfx.FrameInfo.CropH *= 2;
2241 m_mfxDecParams.mfx.FrameInfo.Height = MSDK_ALIGN16(m_mfxDecParams.mfx.FrameInfo.CropH);
2242 m_mfxDecParams.mfx.FrameInfo.PicStruct = m_pmfxBS->PicStruct;
2243 }
2244 }
2245 else
2246 {
2247 m_mfxDecParams.mfx.FrameInfo.Width = MSDK_ALIGN32(pInParams->nVppCompSrcW);
2248 m_mfxDecParams.mfx.FrameInfo.Height = MSDK_ALIGN32(pInParams->nVppCompSrcH);
2249 m_mfxDecParams.mfx.FrameInfo.CropW = pInParams->nVppCompSrcW;
2250 m_mfxDecParams.mfx.FrameInfo.CropH = pInParams->nVppCompSrcH;
2251
2252 m_mfxDecParams.mfx.FrameInfo.AspectRatioW = m_mfxDecParams.mfx.FrameInfo.AspectRatioH = 1;
2253 m_mfxDecParams.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
2254 m_mfxDecParams.mfx.FrameInfo.FourCC = MFX_FOURCC_RGB4;
2255 }
2256
2257 // set memory pattern
2258 if (m_bUseOpaqueMemory)
2259 m_mfxDecParams.IOPattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
2260 else if (pInParams->bForceSysMem || (MFX_IMPL_SOFTWARE == pInParams->libType)
2261 || (pInParams->DecOutPattern == MFX_IOPATTERN_OUT_SYSTEM_MEMORY))
2262 m_mfxDecParams.IOPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
2263 else
2264 m_mfxDecParams.IOPattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY;
2265
2266 // if frame rate specified by user set it for decoder output
2267 if (pInParams->dDecoderFrameRateOverride)
2268 {
2269 ConvertFrameRate(pInParams->dDecoderFrameRateOverride, &m_mfxDecParams.mfx.FrameInfo.FrameRateExtN, &m_mfxDecParams.mfx.FrameInfo.FrameRateExtD);
2270 }
2271 // if frame rate not specified and input stream header doesn't contain valid values use default (30.0)
2272 else if (0 == (m_mfxDecParams.mfx.FrameInfo.FrameRateExtN * m_mfxDecParams.mfx.FrameInfo.FrameRateExtD))
2273 {
2274 m_mfxDecParams.mfx.FrameInfo.FrameRateExtN = 30;
2275 m_mfxDecParams.mfx.FrameInfo.FrameRateExtD = 1;
2276 }
2277 else
2278 {
2279 // use the value from input stream header
2280 }
2281
2282 //--- Force setting fourcc type if required
2283 if(pInParams->DecoderFourCC)
2284 {
2285 m_mfxDecParams.mfx.FrameInfo.FourCC=pInParams->DecoderFourCC;
2286 m_mfxDecParams.mfx.FrameInfo.ChromaFormat=FourCCToChroma(pInParams->DecoderFourCC);
2287 }
2288
2289 #if MFX_VERSION >= 1022
2290 /* SFC usage if enabled */
2291 if (pInParams->bDecoderPostProcessing)
2292 {
2293 auto decPostProc = m_mfxDecParams.AddExtBuffer<mfxExtDecVideoProcessing>();
2294 decPostProc->In.CropX = 0;
2295 decPostProc->In.CropY = 0;
2296 decPostProc->In.CropW = m_mfxDecParams.mfx.FrameInfo.CropW;
2297 decPostProc->In.CropH = m_mfxDecParams.mfx.FrameInfo.CropH;
2298
2299 decPostProc->Out.FourCC = m_mfxDecParams.mfx.FrameInfo.FourCC;
2300 decPostProc->Out.ChromaFormat = m_mfxDecParams.mfx.FrameInfo.ChromaFormat;
2301 decPostProc->Out.CropX = 0;
2302 decPostProc->Out.CropY = 0;
2303 decPostProc->Out.CropW = pInParams->eModeExt == VppComp ? pInParams->nVppCompDstW : pInParams->nDstWidth;
2304 decPostProc->Out.CropH = pInParams->eModeExt == VppComp ? pInParams->nVppCompDstH : pInParams->nDstHeight;
2305 decPostProc->Out.Width = MSDK_ALIGN16(decPostProc->Out.CropW);
2306 decPostProc->Out.Height = MSDK_ALIGN16(decPostProc->Out.CropH);
2307 }
2308 #endif
2309
2310 return MFX_ERR_NONE;
2311 }// mfxStatus CTranscodingPipeline::InitDecMfxParams()
2312
2313
FillFrameInfoForEncoding(mfxFrameInfo & info,sInputParams * pInParams)2314 void CTranscodingPipeline::FillFrameInfoForEncoding(mfxFrameInfo& info, sInputParams *pInParams)
2315 {
2316 // Getting parameters from previous blocks
2317 if (m_bIsVpp)
2318 {
2319 MSDK_MEMCPY_VAR(info, &m_mfxVppParams.vpp.Out, sizeof(mfxFrameInfo));
2320 }
2321 else if (m_bIsPlugin)
2322 {
2323 info = m_mfxPluginParams.vpp.Out;
2324 }
2325 else
2326 {
2327 info = GetFrameInfo(m_mfxDecParams);
2328 }
2329
2330 if (pInParams->dEncoderFrameRateOverride)
2331 {
2332 ConvertFrameRate(pInParams->dEncoderFrameRateOverride, &info.FrameRateExtN, &info.FrameRateExtD);
2333 }
2334 else if (pInParams->dVPPOutFramerate)
2335 {
2336 ConvertFrameRate(pInParams->dVPPOutFramerate, &info.FrameRateExtN, &info.FrameRateExtD);
2337 }
2338 }
2339
InitEncMfxParams(sInputParams * pInParams)2340 mfxStatus CTranscodingPipeline::InitEncMfxParams(sInputParams *pInParams)
2341 {
2342 MSDK_CHECK_POINTER(pInParams, MFX_ERR_NULL_PTR);
2343
2344 FillFrameInfoForEncoding(m_mfxEncParams.mfx.FrameInfo, pInParams);
2345
2346 MSDK_CHECK_ERROR(m_mfxEncParams.mfx.FrameInfo.FrameRateExtN * m_mfxEncParams.mfx.FrameInfo.FrameRateExtD,
2347 0, MFX_ERR_INVALID_VIDEO_PARAM);
2348
2349 m_mfxEncParams.mfx.CodecId = pInParams->EncodeId;
2350 m_mfxEncParams.mfx.TargetUsage = pInParams->nTargetUsage; // trade-off between quality and speed
2351 m_mfxEncParams.AsyncDepth = m_AsyncDepth;
2352 m_mfxEncParams.mfx.FrameInfo.Shift = m_shouldUseShifted10BitEnc;
2353
2354 if (pInParams->nTransferCharacteristics)
2355 {
2356 auto videoSignalInfo = m_mfxEncParams.AddExtBuffer<mfxExtVideoSignalInfo>();
2357 videoSignalInfo->ColourDescriptionPresent = 1;
2358 videoSignalInfo->TransferCharacteristics = pInParams->nTransferCharacteristics;
2359 // Fill in VUI parameters
2360 switch (videoSignalInfo->TransferCharacteristics)
2361 {
2362 case 18: //HLG (BT.2020)
2363 videoSignalInfo->ColourPrimaries = 9;
2364 videoSignalInfo->MatrixCoefficients = 9;
2365 break;
2366 case 1: //BT.709
2367 default:
2368 videoSignalInfo->ColourPrimaries = 1;
2369 videoSignalInfo->MatrixCoefficients = 1;
2370 break;
2371 }
2372 }
2373 #if (MFX_VERSION >= 1025)
2374 if(pInParams->numMFEFrames || pInParams->MFMode)
2375 {
2376 auto mfePar = m_mfxEncParams.AddExtBuffer<mfxExtMultiFrameParam>();
2377 mfePar->MaxNumFrames = pInParams->numMFEFrames;
2378 mfePar->MFMode = pInParams->MFMode;
2379 }
2380
2381 if(pInParams->mfeTimeout)
2382 {
2383 auto mfeCtrl = m_mfxEncParams.AddExtBuffer<mfxExtMultiFrameControl>();
2384 mfeCtrl->Timeout = pInParams->mfeTimeout;
2385 }
2386 #endif
2387 if (m_pParentPipeline && m_pParentPipeline->m_pmfxPreENC.get())
2388 {
2389 m_mfxEncParams.mfx.RateControlMethod = MFX_RATECONTROL_LA_EXT;
2390 m_mfxEncParams.mfx.EncodedOrder = 1; // binary flag, 0 signals encoder to take frames in display order
2391 m_mfxEncParams.AsyncDepth = m_mfxEncParams.AsyncDepth == 0 ? 2: m_mfxEncParams.AsyncDepth;
2392 }
2393 else
2394 {
2395 m_mfxEncParams.mfx.RateControlMethod = pInParams->nRateControlMethod;
2396 }
2397 m_mfxEncParams.mfx.NumSlice = pInParams->nSlices;
2398
2399 if (pInParams->nRateControlMethod == MFX_RATECONTROL_CQP)
2400 {
2401 m_mfxEncParams.mfx.QPI = pInParams->nQPI;
2402 m_mfxEncParams.mfx.QPP = pInParams->nQPP;
2403 m_mfxEncParams.mfx.QPB = pInParams->nQPB;
2404 }
2405 else if (pInParams->nRateControlMethod == MFX_RATECONTROL_AVBR)
2406 {
2407 m_mfxEncParams.mfx.Accuracy = pInParams->Accuracy;
2408 m_mfxEncParams.mfx.Convergence = pInParams->Convergence;
2409 }
2410 else if (pInParams->nRateControlMethod == MFX_RATECONTROL_QVBR)
2411 {
2412 auto codingOption3 = m_mfxEncParams.AddExtBuffer<mfxExtCodingOption3>();
2413 codingOption3->QVBRQuality = pInParams->QVBRQuality;
2414 codingOption3->WinBRCMaxAvgKbps = pInParams->WinBRCMaxAvgKbps;
2415 }
2416 else if (pInParams->nRateControlMethod == MFX_RATECONTROL_ICQ)
2417 {
2418 m_mfxEncParams.mfx.ICQQuality = pInParams->ICQQuality;
2419 }
2420
2421 if(pInParams->enableQSVFF)
2422 {
2423 m_mfxEncParams.mfx.LowPower = MFX_CODINGOPTION_ON;
2424 }
2425
2426 // leave PAR unset to avoid MPEG2 encoder rejecting streams with unsupported DAR
2427 m_mfxEncParams.mfx.FrameInfo.AspectRatioW = m_mfxEncParams.mfx.FrameInfo.AspectRatioH = 0;
2428
2429 // calculate default bitrate based on resolution and framerate
2430 if (pInParams->EncoderPicstructOverride)
2431 {
2432 m_mfxEncParams.mfx.FrameInfo.PicStruct = pInParams->EncoderPicstructOverride;
2433 }
2434
2435 MSDK_CHECK_ERROR(m_mfxEncParams.mfx.FrameInfo.FrameRateExtN * m_mfxEncParams.mfx.FrameInfo.FrameRateExtD,
2436 0, MFX_ERR_INVALID_VIDEO_PARAM);
2437
2438 if (pInParams->nRateControlMethod != MFX_RATECONTROL_CQP)
2439 {
2440 if (pInParams->nBitRate == 0)
2441 {
2442 pInParams->nBitRate = CalculateDefaultBitrate(pInParams->EncodeId,
2443 pInParams->nTargetUsage, m_mfxEncParams.mfx.FrameInfo.Width, m_mfxEncParams.mfx.FrameInfo.Height,
2444 1.0 * m_mfxEncParams.mfx.FrameInfo.FrameRateExtN / m_mfxEncParams.mfx.FrameInfo.FrameRateExtD);
2445 }
2446 m_mfxEncParams.mfx.TargetKbps = (mfxU16)pInParams->nBitRate; // in Kbps
2447 m_mfxEncParams.mfx.BRCParamMultiplier = pInParams->nBitRateMultiplier;
2448 }
2449
2450 // In case of HEVC when height and/or width divided with 8 but not divided with 16
2451 // add extended parameter to increase performance
2452 if ( ( !((m_mfxEncParams.mfx.FrameInfo.CropW & 15 ) ^ 8 ) ||
2453 !((m_mfxEncParams.mfx.FrameInfo.CropH & 15 ) ^ 8 ) ) &&
2454 (m_mfxEncParams.mfx.CodecId == MFX_CODEC_HEVC) )
2455 {
2456 auto hevcPar = m_mfxEncParams.AddExtBuffer<mfxExtHEVCParam>();
2457 hevcPar->PicWidthInLumaSamples = m_mfxEncParams.mfx.FrameInfo.CropW;
2458 hevcPar->PicHeightInLumaSamples = m_mfxEncParams.mfx.FrameInfo.CropH;
2459 }
2460 #if (MFX_VERSION >= 1024)
2461 // This is for explicit extbrc only. In case of implicit (built-into-library) version - we don't need this extended buffer
2462 if (pInParams->nExtBRC == EXTBRC_ON &&
2463 (pInParams->EncodeId == MFX_CODEC_HEVC || pInParams->EncodeId == MFX_CODEC_AVC))
2464 {
2465 auto extbrc = m_mfxEncParams.AddExtBuffer<mfxExtBRC>();
2466 HEVCExtBRC::Create(*extbrc);
2467 }
2468 #endif
2469
2470 m_mfxEncParams.mfx.FrameInfo.CropX = 0;
2471 m_mfxEncParams.mfx.FrameInfo.CropY = 0;
2472
2473 mfxU16 InPatternFromParent = (mfxU16) ((MFX_IOPATTERN_OUT_VIDEO_MEMORY == m_mfxDecParams.IOPattern) ?
2474 MFX_IOPATTERN_IN_VIDEO_MEMORY : MFX_IOPATTERN_IN_SYSTEM_MEMORY);
2475
2476 // set memory pattern
2477 if (m_bUseOpaqueMemory)
2478 m_mfxEncParams.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY;
2479 else
2480 m_mfxEncParams.IOPattern = InPatternFromParent;
2481
2482 if (pInParams->nEncTileRows && pInParams->nEncTileCols)
2483 {
2484 if (m_mfxEncParams.mfx.CodecId == MFX_CODEC_HEVC)
2485 {
2486 auto tiles = m_mfxEncParams.AddExtBuffer<mfxExtHEVCTiles>();
2487 tiles->NumTileRows = pInParams->nEncTileRows;
2488 tiles->NumTileColumns = pInParams->nEncTileCols;
2489 }
2490 #if MFX_VERSION >= 1029
2491 else if (m_mfxEncParams.mfx.CodecId == MFX_CODEC_VP9)
2492 {
2493 auto vp9par = m_mfxEncParams.AddExtBuffer<mfxExtVP9Param>();
2494 vp9par->NumTileRows = pInParams->nEncTileRows;
2495 vp9par->NumTileColumns = pInParams->nEncTileCols;
2496 }
2497 #endif
2498 }
2499
2500 if (pInParams->nAvcTemp)
2501 {
2502 if (pInParams->EncodeId == MFX_CODEC_HEVC)
2503 {
2504 auto tl = m_mfxEncParams.AddExtBuffer<mfxExtAvcTemporalLayers>();
2505 tl->BaseLayerPID = pInParams->nBaseLayerPID;
2506 for (int i = 0; i < 8; i++)
2507 {
2508 tl->Layer[i].Scale = pInParams->nAvcTemporalLayers[i];
2509 }
2510 }
2511 }
2512
2513 if (pInParams->nSPSId || pInParams->nPPSId)
2514 {
2515 if (pInParams->EncodeId == MFX_CODEC_HEVC)
2516 {
2517 auto spspps = m_mfxEncParams.AddExtBuffer<mfxExtCodingOptionSPSPPS>();
2518 spspps->SPSId = pInParams->nSPSId;
2519 spspps->PPSId = pInParams->nPPSId;
2520 }
2521 }
2522
2523 if (pInParams->nPicTimingSEI || pInParams->nNalHrdConformance || pInParams->nVuiNalHrdParameters)
2524 {
2525 auto co = m_mfxEncParams.AddExtBuffer<mfxExtCodingOption>();
2526 co->PicTimingSEI = pInParams->nPicTimingSEI;
2527 co->NalHrdConformance = pInParams->nNalHrdConformance;
2528 co->VuiNalHrdParameters = pInParams->nVuiNalHrdParameters;
2529 }
2530
2531 // we don't specify profile and level and let the encoder choose those basing on parameters
2532 // we must specify profile only for MVC codec
2533 if (pInParams->bIsMVC)
2534 {
2535 m_mfxEncParams.mfx.CodecProfile = m_mfxDecParams.mfx.CodecProfile;
2536 }
2537
2538 // JPEG encoder settings overlap nasc other encoders settings in mfxInfoMFX structure
2539 if (MFX_CODEC_JPEG == pInParams->EncodeId)
2540 {
2541 m_mfxEncParams.mfx.Interleaved = 1;
2542 m_mfxEncParams.mfx.Quality = pInParams->nQuality;
2543 m_mfxEncParams.mfx.RestartInterval = 0;
2544 MSDK_ZERO_MEMORY(m_mfxEncParams.mfx.reserved5);
2545 }
2546
2547 // configure and attach external parameters
2548 if (pInParams->bLABRC || pInParams->nMaxSliceSize || pInParams->nBRefType
2549 || (pInParams->BitrateLimit && pInParams->EncodeId == MFX_CODEC_AVC)
2550 || (pInParams->nExtBRC && (pInParams->EncodeId == MFX_CODEC_HEVC || pInParams->EncodeId == MFX_CODEC_AVC))
2551 || pInParams->IntRefType || pInParams->IntRefCycleSize || pInParams->IntRefQPDelta || pInParams->nMaxFrameSize
2552 || pInParams->AdaptiveI || pInParams->AdaptiveB || pInParams->nMinQP || pInParams->nMaxQP)
2553 {
2554 auto co2 = m_mfxEncParams.AddExtBuffer<mfxExtCodingOption2>();
2555 co2->LookAheadDepth = pInParams->nLADepth;
2556 co2->MaxSliceSize = pInParams->nMaxSliceSize;
2557 co2->MaxFrameSize = pInParams->nMaxFrameSize;
2558 co2->BRefType = pInParams->nBRefType;
2559 co2->BitrateLimit = pInParams->BitrateLimit;
2560
2561 co2->IntRefType = pInParams->IntRefType;
2562 co2->IntRefCycleSize = pInParams->IntRefCycleSize;
2563 co2->IntRefQPDelta = pInParams->IntRefQPDelta;
2564 co2->AdaptiveI = pInParams->AdaptiveI;
2565 co2->AdaptiveB = pInParams->AdaptiveB;
2566
2567 if (pInParams->nExtBRC != EXTBRC_DEFAULT && (pInParams->EncodeId == MFX_CODEC_HEVC || pInParams->EncodeId == MFX_CODEC_AVC))
2568 {
2569 co2->ExtBRC =(mfxU16)(pInParams->nExtBRC == EXTBRC_OFF ? MFX_CODINGOPTION_OFF : MFX_CODINGOPTION_ON);
2570 }
2571 else
2572 {
2573 co2->ExtBRC = MFX_CODINGOPTION_UNKNOWN;
2574 }
2575
2576 if (pInParams->nRateControlMethod != MFX_RATECONTROL_CQP)
2577 {
2578 co2->MinQPI = co2->MinQPP = co2->MinQPB =(mfxU8)(pInParams->nMinQP);
2579 co2->MaxQPI = co2->MaxQPP = co2->MaxQPB =(mfxU8)(pInParams->nMaxQP);
2580 }
2581 }
2582
2583 if (pInParams->WinBRCMaxAvgKbps || pInParams->WinBRCSize)
2584 {
2585 auto co3 = m_mfxEncParams.AddExtBuffer<mfxExtCodingOption3>();
2586 co3->WinBRCMaxAvgKbps = pInParams->WinBRCMaxAvgKbps;
2587 co3->WinBRCSize = pInParams->WinBRCSize;
2588 }
2589 #if MFX_VERSION >= 1022
2590 if (pInParams->bROIasQPMAP || pInParams->bExtMBQP)
2591 {
2592 auto co3 = m_mfxEncParams.AddExtBuffer<mfxExtCodingOption3>();
2593 // QP map defines QP value for every 16x16 sub-block of a frame
2594 m_QPmapWidth = (m_mfxEncParams.mfx.FrameInfo.Width + 15) >> 4;
2595 m_QPmapHeight = (m_mfxEncParams.mfx.FrameInfo.Height + 15) >> 4;
2596 co3->EnableMBQP = MFX_CODINGOPTION_ON;
2597 }
2598 #endif
2599
2600 if (pInParams->WeightedPred || pInParams->WeightedBiPred ||
2601 pInParams->IntRefCycleDist ||
2602 pInParams->nAdaptiveMaxFrameSize || pInParams->LowDelayBRC)
2603 {
2604 auto co3 = m_mfxEncParams.AddExtBuffer<mfxExtCodingOption3>();
2605 co3->WeightedPred = pInParams->WeightedPred;
2606 co3->WeightedBiPred = pInParams->WeightedBiPred;
2607 co3->LowDelayBRC = pInParams->LowDelayBRC;
2608 co3->IntRefCycleDist = pInParams->IntRefCycleDist;
2609 co3->AdaptiveMaxFrameSize = pInParams->nAdaptiveMaxFrameSize;
2610 }
2611 #if (MFX_VERSION >= 1026)
2612 if (pInParams->ExtBrcAdaptiveLTR)
2613 {
2614 auto co3 = m_mfxEncParams.AddExtBuffer<mfxExtCodingOption3>();
2615 co3->ExtBrcAdaptiveLTR = pInParams->ExtBrcAdaptiveLTR;
2616 }
2617 #endif
2618 #if MFX_VERSION >= 1023
2619 if (pInParams->RepartitionCheckMode)
2620 {
2621 auto co3 = m_mfxEncParams.AddExtBuffer<mfxExtCodingOption3>();
2622 co3->RepartitionCheckEnable = pInParams->RepartitionCheckMode;
2623 }
2624 #endif
2625
2626 if (pInParams->GPB)
2627 {
2628 auto co3 = m_mfxEncParams.AddExtBuffer<mfxExtCodingOption3>();
2629 co3->GPB = pInParams->GPB;
2630 }
2631 #if (MFX_VERSION >= 1026)
2632 if (pInParams->nTransformSkip)
2633 {
2634 auto co3 = m_mfxEncParams.AddExtBuffer<mfxExtCodingOption3>();
2635 co3->TransformSkip = pInParams->nTransformSkip;
2636 }
2637 #endif
2638 if (pInParams->bDisableQPOffset)
2639 {
2640 auto co3 = m_mfxEncParams.AddExtBuffer<mfxExtCodingOption3>();
2641 co3->EnableQPOffset = MFX_CODINGOPTION_OFF;
2642 }
2643
2644 if (m_bUseOpaqueMemory)
2645 m_mfxEncParams.AddExtBuffer<mfxExtOpaqueSurfaceAlloc>();
2646
2647 if (pInParams->bIsMVC)
2648 m_mfxEncParams.AddExtBuffer<mfxExtMVCSeqDesc>();
2649
2650 #if (MFX_VERSION >= 1027)
2651 if (pInParams->TargetBitDepthLuma)
2652 {
2653 auto co3 = m_mfxEncParams.AddExtBuffer<mfxExtCodingOption3>();
2654 co3->TargetBitDepthLuma = pInParams->TargetBitDepthLuma;
2655 }
2656 if (pInParams->TargetBitDepthChroma)
2657 {
2658 auto co3 = m_mfxEncParams.AddExtBuffer<mfxExtCodingOption3>();
2659 co3->TargetBitDepthChroma = pInParams->TargetBitDepthChroma;
2660 }
2661 #endif
2662
2663 if (m_pParentPipeline)
2664 {
2665 m_pParentPipeline->AddLaStreams(m_mfxEncParams.mfx.FrameInfo.Width,m_mfxEncParams.mfx.FrameInfo.Height);
2666 }
2667
2668 //--- Settings HRD buffer size
2669 if (pInParams->BufferSizeInKB)
2670 {
2671 m_mfxEncParams.mfx.BufferSizeInKB = (mfxU16)pInParams->BufferSizeInKB;
2672 }
2673
2674 //--- Force setting fourcc type if required
2675 if (pInParams->EncoderFourCC)
2676 {
2677 m_mfxEncParams.mfx.FrameInfo.FourCC=pInParams->EncoderFourCC;
2678 m_mfxEncParams.mfx.FrameInfo.ChromaFormat=FourCCToChroma(pInParams->EncoderFourCC);
2679 }
2680
2681 // GopPicSize and GopRefDist values are always set using presets manager, but do not set them for JPEG
2682 if (MFX_CODEC_JPEG != pInParams->EncodeId)
2683 {
2684 m_mfxEncParams.mfx.GopPicSize = pInParams->GopPicSize;
2685 m_mfxEncParams.mfx.GopRefDist = pInParams->GopRefDist;
2686 }
2687
2688 if (pInParams->NumRefFrame)
2689 {
2690 m_mfxEncParams.mfx.NumRefFrame = pInParams->NumRefFrame;
2691 }
2692
2693 if (pInParams->CodecLevel)
2694 {
2695 m_mfxEncParams.mfx.CodecLevel = pInParams->CodecLevel;
2696 }
2697
2698 if (pInParams->CodecProfile)
2699 {
2700 m_mfxEncParams.mfx.CodecProfile = pInParams->CodecProfile;
2701 }
2702
2703 if (pInParams->GopOptFlag)
2704 {
2705 m_mfxEncParams.mfx.GopOptFlag = pInParams->GopOptFlag;
2706 }
2707
2708 if (pInParams->MaxKbps)
2709 {
2710 m_mfxEncParams.mfx.MaxKbps = (mfxU16)pInParams->MaxKbps;
2711 }
2712
2713 if (pInParams->InitialDelayInKB)
2714 {
2715 m_mfxEncParams.mfx.InitialDelayInKB = (mfxU16)pInParams->InitialDelayInKB;
2716 }
2717
2718 if (pInParams->nBitRateMultiplier)
2719 {
2720 m_mfxEncParams.mfx.BRCParamMultiplier = pInParams->nBitRateMultiplier;
2721 }
2722
2723 return MFX_ERR_NONE;
2724 }// mfxStatus CTranscodingPipeline::InitEncMfxParams(sInputParams *pInParams)
2725
CorrectPreEncAuxPool(mfxU32 num_frames_in_pool)2726 mfxStatus CTranscodingPipeline::CorrectPreEncAuxPool(mfxU32 num_frames_in_pool)
2727 {
2728 if (!m_pmfxPreENC) return MFX_ERR_NONE;
2729
2730 if (m_pPreEncAuxPool.size() < num_frames_in_pool)
2731 {
2732 m_pPreEncAuxPool.resize(num_frames_in_pool);
2733 }
2734 return MFX_ERR_NONE;
2735 }
2736
AllocPreEncAuxPool()2737 mfxStatus CTranscodingPipeline::AllocPreEncAuxPool()
2738 {
2739 if (!m_pmfxPreENC)
2740 return MFX_ERR_NONE;
2741
2742 auto laCtrl = m_mfxPreEncParams.AddExtBuffer<mfxExtLAControl>();
2743 mfxU16 num_resolutions = laCtrl->NumOutStream;
2744 int buff_size = sizeof(mfxExtLAFrameStatistics) +
2745 sizeof(mfxLAFrameInfo)*num_resolutions*laCtrl->LookAheadDepth;
2746
2747 for (size_t i = 0; i < m_pPreEncAuxPool.size(); i++)
2748 {
2749 memset(&m_pPreEncAuxPool[i],0,sizeof(m_pPreEncAuxPool[i]));
2750
2751 m_pPreEncAuxPool[i].encCtrl.NumExtParam = 1;
2752 m_pPreEncAuxPool[i].encCtrl.ExtParam = new mfxExtBuffer*[1];
2753
2754 char *pBuff = new char[buff_size];
2755 memset(pBuff,0, buff_size);
2756
2757 m_pPreEncAuxPool[i].encCtrl.ExtParam[0] = (mfxExtBuffer *)pBuff;
2758 mfxExtLAFrameStatistics *pExtBuffer = (mfxExtLAFrameStatistics *)pBuff;
2759
2760 pExtBuffer = (mfxExtLAFrameStatistics*) pBuff;
2761 pExtBuffer->Header.BufferId = MFX_EXTBUFF_LOOKAHEAD_STAT;
2762 pExtBuffer->Header.BufferSz = buff_size;
2763 pExtBuffer->NumAlloc = num_resolutions*laCtrl->LookAheadDepth;
2764 pExtBuffer->FrameStat = (mfxLAFrameInfo *)(pBuff + sizeof(mfxExtLAFrameStatistics));
2765
2766 m_pPreEncAuxPool[i].encOutput.NumExtParam = 1;
2767 m_pPreEncAuxPool[i].encOutput.ExtParam = m_pPreEncAuxPool[i].encCtrl.ExtParam;
2768 }
2769 return MFX_ERR_NONE;
2770 }
2771
FreePreEncAuxPool()2772 void CTranscodingPipeline::FreePreEncAuxPool()
2773 {
2774 for (size_t i = 0; i < m_pPreEncAuxPool.size(); i++)
2775 {
2776 if(m_pPreEncAuxPool[i].encCtrl.ExtParam)
2777 {
2778 delete [] m_pPreEncAuxPool[i].encCtrl.ExtParam[0];
2779 delete [] m_pPreEncAuxPool[i].encCtrl.ExtParam;
2780 }
2781 }
2782 m_pPreEncAuxPool.resize(0);
2783 }
2784
LoadStaticSurface()2785 mfxStatus TranscodingSample::CTranscodingPipeline::LoadStaticSurface()
2786 {
2787 if (m_bUseOverlay)
2788 {
2789 mfxFrameSurface1* pSurf = m_pSurfaceDecPool[0];
2790 mfxStatus sts = m_pMFXAllocator->LockFrame(pSurf->Data.MemId, &pSurf->Data);
2791 MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->LockFrame failed");
2792 sts = m_pBSProcessor->GetInputFrame(pSurf);
2793 MSDK_CHECK_STATUS(sts, "m_YUVReader->LoadNextFrame failed");
2794 sts = m_pMFXAllocator->UnlockFrame(pSurf->Data.MemId, &pSurf->Data);
2795 MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->UnlockFrame failed");
2796 }
2797 return MFX_ERR_NONE;
2798 }
2799
InitPreEncMfxParams(sInputParams * pInParams)2800 mfxStatus CTranscodingPipeline::InitPreEncMfxParams(sInputParams *pInParams)
2801 {
2802 MSDK_CHECK_ERROR(pInParams->bEnableExtLA, false, MFX_ERR_INVALID_VIDEO_PARAM);
2803 MSDK_CHECK_POINTER(pInParams, MFX_ERR_NULL_PTR);
2804
2805 mfxVideoParam & param = m_mfxPreEncParams;
2806
2807 param.AsyncDepth = m_AsyncDepth;
2808
2809 MSDK_ZERO_MEMORY(param.mfx);
2810 param.mfx.CodecId= MFX_CODEC_AVC;
2811 param.mfx.TargetUsage= pInParams->nTargetUsage;
2812
2813 if (m_bIsVpp)
2814 {
2815 MSDK_MEMCPY_VAR(param.mfx.FrameInfo, &m_mfxVppParams.vpp.Out, sizeof(mfxFrameInfo));
2816 }
2817 else if (m_bIsPlugin)
2818 {
2819 MSDK_MEMCPY_VAR(param.mfx.FrameInfo, &m_mfxPluginParams.vpp.Out, sizeof(mfxFrameInfo));
2820 }
2821 else
2822 {
2823 param.mfx.FrameInfo = GetFrameInfo(m_mfxDecParams);
2824 }
2825
2826 mfxU16 InPatternFromParent = (mfxU16) ((MFX_IOPATTERN_OUT_VIDEO_MEMORY == m_mfxDecParams.IOPattern) ?
2827 MFX_IOPATTERN_IN_VIDEO_MEMORY : MFX_IOPATTERN_IN_SYSTEM_MEMORY);
2828
2829 // set memory pattern
2830 if (m_bUseOpaqueMemory)
2831 param.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY;
2832 else
2833 param.IOPattern = InPatternFromParent;
2834
2835 // configure and attach external parameters
2836 if (m_bUseOpaqueMemory)
2837 m_mfxPreEncParams.AddExtBuffer<mfxExtOpaqueSurfaceAlloc>();
2838
2839 auto laCtrl = m_mfxPreEncParams.AddExtBuffer<mfxExtLAControl>();
2840 laCtrl->LookAheadDepth = pInParams->nLADepth? pInParams->nLADepth : 40;
2841 laCtrl->NumOutStream = 0;
2842 laCtrl->BPyramid = (mfxU16)(pInParams->bEnableBPyramid ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF);
2843
2844 m_mfxPreEncParams.mfx.GopPicSize = pInParams->GopPicSize ? pInParams->GopPicSize : 1500;
2845
2846 if (pInParams->GopRefDist)
2847 {
2848 m_mfxPreEncParams.mfx.GopRefDist = pInParams->GopRefDist;
2849 }
2850
2851 if (pInParams->nTargetUsage)
2852 {
2853 m_mfxPreEncParams.mfx.TargetUsage = pInParams->nTargetUsage;
2854 }
2855
2856 return MFX_ERR_NONE;
2857 }
2858
AddLaStreams(mfxU16 width,mfxU16 height)2859 mfxStatus CTranscodingPipeline::AddLaStreams(mfxU16 width, mfxU16 height)
2860 {
2861 if (m_pmfxPreENC.get() != NULL)
2862 {
2863 auto laCtrl = m_mfxPreEncParams.AddExtBuffer<mfxExtLAControl>();
2864 mfxU32 num = laCtrl->NumOutStream;
2865 m_numEncoders ++;
2866 for (mfxU32 i = 0; i < num; i++)
2867 {
2868 if (laCtrl->OutStream[i].Width == width && laCtrl->OutStream[i].Height == height)
2869 return MFX_ERR_NONE;
2870 }
2871 if ((sizeof(laCtrl->OutStream) / sizeof(laCtrl->OutStream[0])) < (num + 1))
2872 return MFX_ERR_UNSUPPORTED;
2873
2874 laCtrl->OutStream[num].Width = width;
2875 laCtrl->OutStream[num].Height = height;
2876 laCtrl->NumOutStream = (mfxU16)num + 1;
2877 }
2878 return MFX_ERR_NONE;
2879 }
2880
FileFourCC2EncFourCC(mfxU32 fcc)2881 mfxU32 CTranscodingPipeline::FileFourCC2EncFourCC(mfxU32 fcc)
2882 {
2883 if (fcc == MFX_FOURCC_I420)
2884 return MFX_FOURCC_NV12;
2885 else
2886 return fcc;
2887 }
2888
InitVppMfxParams(sInputParams * pInParams)2889 mfxStatus CTranscodingPipeline::InitVppMfxParams(sInputParams *pInParams)
2890 {
2891 MSDK_CHECK_POINTER(pInParams, MFX_ERR_NULL_PTR);
2892 m_mfxVppParams.AsyncDepth = m_AsyncDepth;
2893
2894 mfxU16 InPatternFromParent = (mfxU16)((MFX_IOPATTERN_OUT_VIDEO_MEMORY == m_mfxDecParams.IOPattern) ?
2895 MFX_IOPATTERN_IN_VIDEO_MEMORY : MFX_IOPATTERN_IN_SYSTEM_MEMORY);
2896
2897 // set memory pattern
2898 if (pInParams->VppOutPattern)
2899 {
2900 m_mfxVppParams.IOPattern = (mfxU16)(InPatternFromParent | pInParams->VppOutPattern);
2901 }
2902 else if (m_bUseOpaqueMemory)
2903 {
2904 m_mfxVppParams.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY|MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
2905 }
2906 else if (pInParams->bForceSysMem || (MFX_IMPL_SOFTWARE == pInParams->libType) || m_rawInput)
2907 {
2908 m_mfxVppParams.IOPattern = (mfxU16)(InPatternFromParent|MFX_IOPATTERN_OUT_SYSTEM_MEMORY);
2909 }
2910 else
2911 {
2912 m_mfxVppParams.IOPattern = (mfxU16)(InPatternFromParent|MFX_IOPATTERN_OUT_VIDEO_MEMORY);
2913 }
2914
2915 // Fill Shift bit
2916 m_mfxVppParams.vpp.In.Shift = m_shouldUseShifted10BitVPP;
2917 m_mfxVppParams.vpp.Out.Shift =
2918 m_shouldUseShifted10BitEnc; // This output should correspond to Encoder settings
2919
2920 // input frame info
2921 m_mfxVppParams.vpp.In = GetFrameInfo(m_mfxDecParams);
2922
2923 if (m_mfxVppParams.vpp.In.Width * m_mfxVppParams.vpp.In.Height == 0)
2924 {
2925 m_mfxVppParams.vpp.In.Width = MSDK_ALIGN32(pInParams->nDstWidth);
2926 m_mfxVppParams.vpp.In.Height = MSDK_ALIGN32(pInParams->nDstHeight);
2927 }
2928
2929 if (m_mfxVppParams.vpp.In.CropW * m_mfxVppParams.vpp.In.CropH == 0)
2930 {
2931 m_mfxVppParams.vpp.In.CropW = pInParams->nDstWidth;
2932 m_mfxVppParams.vpp.In.CropH = pInParams->nDstHeight;
2933 }
2934
2935 if (m_mfxVppParams.vpp.In.FrameRateExtN * m_mfxVppParams.vpp.In.FrameRateExtD == 0)
2936 {
2937 m_mfxVppParams.vpp.In.FrameRateExtN = 30;
2938 m_mfxVppParams.vpp.In.FrameRateExtD = 1;
2939 }
2940
2941 if (m_mfxVppParams.vpp.In.FourCC == 0)
2942 {
2943 m_mfxVppParams.vpp.In.FourCC = FileFourCC2EncFourCC(pInParams->DecodeId);
2944 m_mfxVppParams.mfx.FrameInfo.ChromaFormat = FourCCToChroma(pInParams->DecoderFourCC);
2945 }
2946
2947 if (m_rawInput)
2948 {
2949 m_mfxVppParams.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
2950 }
2951
2952 // fill output frame info
2953 MSDK_MEMCPY_VAR(m_mfxVppParams.vpp.Out, &m_mfxVppParams.vpp.In, sizeof(mfxFrameInfo));
2954
2955
2956 if(m_bIsFieldWeaving)
2957 {
2958 m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_UNKNOWN;
2959 m_mfxVppParams.vpp.Out.Height = m_mfxVppParams.vpp.In.Height << 1;
2960 m_mfxVppParams.vpp.Out.CropH = m_mfxVppParams.vpp.In.CropH << 1;
2961 }
2962
2963 if(m_bIsFieldSplitting)
2964 {
2965 m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_SINGLE;
2966 m_mfxVppParams.vpp.Out.Height = m_mfxVppParams.vpp.In.Height >> 1;
2967 m_mfxVppParams.vpp.Out.CropH = m_mfxVppParams.vpp.In.CropH >> 1;
2968 }
2969 if (pInParams->bEnableDeinterlacing)
2970 m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
2971
2972
2973 // Resizing
2974 if (pInParams->nDstWidth)
2975 {
2976 m_mfxVppParams.vpp.Out.CropW = pInParams->nDstWidth;
2977 m_mfxVppParams.vpp.Out.Width = MSDK_ALIGN16(pInParams->nDstWidth);
2978 }
2979
2980 // Framerate conversion
2981 if(pInParams->dVPPOutFramerate)
2982 {
2983 ConvertFrameRate(pInParams->dVPPOutFramerate, &m_mfxVppParams.vpp.Out.FrameRateExtN, &m_mfxVppParams.vpp.Out.FrameRateExtD);
2984 }
2985
2986 if (pInParams->nDstHeight)
2987 {
2988 m_mfxVppParams.vpp.Out.CropH = pInParams->nDstHeight;
2989 m_mfxVppParams.vpp.Out.Height = (MFX_PICSTRUCT_PROGRESSIVE == m_mfxVppParams.vpp.Out.PicStruct) ?
2990 MSDK_ALIGN16(pInParams->nDstHeight) : MSDK_ALIGN32(pInParams->nDstHeight);
2991 }
2992
2993
2994 if (pInParams->bEnableDeinterlacing)
2995 {
2996 // If stream were interlaced before then 32 bit alignment were applied.
2997 // Discard 32 bit alignment as progressive doesn't require it.
2998 m_mfxVppParams.vpp.Out.Height = MSDK_ALIGN16(m_mfxVppParams.vpp.Out.CropH);
2999 m_mfxVppParams.vpp.Out.Width = MSDK_ALIGN16(m_mfxVppParams.vpp.Out.CropW);
3000 }
3001
3002 // configure and attach external parameters
3003 mfxStatus sts = AllocAndInitVppDoNotUse(pInParams);
3004 MSDK_CHECK_STATUS(sts, "AllocAndInitVppDoNotUse failed");
3005
3006 //--- Setting output FourCC type (input type is taken from m_mfxDecParams)
3007 if (pInParams->EncoderFourCC)
3008 {
3009 m_mfxVppParams.vpp.Out.FourCC = pInParams->EncoderFourCC;
3010 m_mfxVppParams.vpp.Out.ChromaFormat = FourCCToChroma(pInParams->EncoderFourCC);
3011
3012 // set bit depth according to FourCC, it must be not inherited from m_mfxVppParams.vpp.In
3013 switch (m_mfxVppParams.vpp.Out.FourCC)
3014 {
3015 case MFX_FOURCC_RGB4:
3016 case MFX_FOURCC_YUY2:
3017 case MFX_FOURCC_NV12:
3018 case MFX_FOURCC_NV16:
3019 m_mfxVppParams.vpp.Out.BitDepthLuma = m_mfxVppParams.vpp.Out.BitDepthChroma = 8;
3020 break;
3021 case MFX_FOURCC_P010:
3022 case MFX_FOURCC_P210:
3023 #if (MFX_VERSION >= 1027)
3024 case MFX_FOURCC_Y210:
3025 case MFX_FOURCC_Y410:
3026 #endif
3027 m_mfxVppParams.vpp.Out.BitDepthLuma = m_mfxVppParams.vpp.Out.BitDepthChroma = 10;
3028 break;
3029 default:
3030 assert(0);
3031 MSDK_CHECK_STATUS(MFX_ERR_UNSUPPORTED, "Unexpected encoder FourCC");
3032 }
3033 }
3034
3035 /* VPP Comp Init */
3036 if (((pInParams->eModeExt == VppComp) || (pInParams->eModeExt == VppCompOnly)) && (pInParams->numSurf4Comp != 0))
3037 {
3038 if(m_nVPPCompEnable != VppCompOnlyEncode)
3039 m_nVPPCompEnable = pInParams->eModeExt;
3040
3041 auto vppCompPar = m_mfxVppParams.AddExtBuffer<mfxExtVPPComposite>();
3042 vppCompPar->NumInputStream = (mfxU16)pInParams->numSurf4Comp;
3043 vppCompPar->InputStream = (mfxVPPCompInputStream *)malloc( sizeof(mfxVPPCompInputStream)* vppCompPar->NumInputStream );
3044 MSDK_CHECK_POINTER(vppCompPar->InputStream, MFX_ERR_NULL_PTR);
3045
3046 // stream params
3047 /* if input streams in NV12 format background color should be in YUV format too
3048 * The same for RGB4 input, background color should be in ARGB format
3049 * */
3050
3051 switch(pInParams->EncoderFourCC)
3052 {
3053 case MFX_FOURCC_RGB4:
3054 /* back color in RGB */
3055 vppCompPar->R = 0x00;
3056 vppCompPar->G = 0x00;
3057 vppCompPar->B = 0x00;
3058 break;
3059 case MFX_FOURCC_NV12:
3060 case MFX_FOURCC_P010:
3061 case MFX_FOURCC_NV16:
3062 case MFX_FOURCC_P210:
3063 case MFX_FOURCC_YUY2:
3064 default:
3065 /* back color in YUV */
3066 vppCompPar->Y = 0x10;
3067 vppCompPar->U = 0x80;
3068 vppCompPar->V = 0x80;
3069 break;
3070 }
3071
3072 #if MFX_VERSION >= 1024
3073 vppCompPar->NumTiles = pInParams->numTiles4Comp;
3074 #endif
3075
3076 MSDK_CHECK_POINTER(pInParams->pVppCompDstRects, MFX_ERR_NULL_PTR);
3077 for (mfxU32 i = 0; i < pInParams->numSurf4Comp; i++)
3078 {
3079 vppCompPar->InputStream[i].DstX = pInParams->pVppCompDstRects[i].DstX;
3080 vppCompPar->InputStream[i].DstY = pInParams->pVppCompDstRects[i].DstY;
3081 vppCompPar->InputStream[i].DstW = pInParams->pVppCompDstRects[i].DstW;
3082 vppCompPar->InputStream[i].DstH = pInParams->pVppCompDstRects[i].DstH;
3083 #if MFX_VERSION >= 1024
3084 vppCompPar->InputStream[i].TileId = pInParams->pVppCompDstRects[i].TileId;
3085 #endif
3086 vppCompPar->InputStream[i].GlobalAlpha = 0;
3087 vppCompPar->InputStream[i].GlobalAlphaEnable = 0;
3088 vppCompPar->InputStream[i].PixelAlphaEnable = 0;
3089
3090 vppCompPar->InputStream[i].LumaKeyEnable = 0;
3091 vppCompPar->InputStream[i].LumaKeyMin = 0;
3092 vppCompPar->InputStream[i].LumaKeyMax = 0;
3093 }
3094 }
3095
3096 if (m_bUseOpaqueMemory)
3097 m_mfxVppParams.AddExtBuffer<mfxExtOpaqueSurfaceAlloc>();
3098
3099 if (pInParams->bIsMVC)
3100 m_mfxVppParams.AddExtBuffer<mfxExtMVCSeqDesc>();
3101
3102 mfxU32 enhFilterCount = 0;
3103
3104 #ifdef ENABLE_MCTF
3105 if (VPP_FILTER_ENABLED_CONFIGURED == pInParams->mctfParam.mode)
3106 {
3107 auto mctf = m_mfxVppParams.AddExtBuffer<mfxExtVppMctf>();
3108 mctf->FilterStrength = pInParams->mctfParam.params.FilterStrength;
3109 // If an external file is given & at least 1 value is given, use it
3110 if (!pInParams->mctfParam.rtParams.Empty() && pInParams->mctfParam.rtParams.GetCurParam())
3111 {
3112 mctf->FilterStrength = pInParams->mctfParam.rtParams.GetCurParam()->FilterStrength;
3113 }
3114 #if defined ENABLE_MCTF_EXT
3115 mctf->Overlap = pInParams->mctfParam.pInParams.Overlap;
3116 mctf->TemporalMode = pInParams->mctfParam.params.TemporalMode;
3117 mctf->MVPrecision = pInParams->mctfParam.params.MVPrecision;
3118 mctf->BitsPerPixelx100k = pInParams->mctfParam.params.BitsPerPixelx100k;
3119 mctf->Deblocking = pInParams->mctfParam.params.Deblocking;
3120 #endif
3121 }
3122 else if (VPP_FILTER_ENABLED_DEFAULT == pInParams->mctfParam.mode)
3123 {
3124 // MCTF enabling through do-use list:
3125 m_tabDoUseAlg[enhFilterCount++] = MFX_EXTBUFF_VPP_MCTF;
3126 }
3127 #endif //ENABLE_MCTF
3128
3129 if (pInParams->DenoiseLevel != -1)
3130 {
3131 auto denoise = m_mfxVppParams.AddExtBuffer<mfxExtVPPDenoise>();
3132 denoise->DenoiseFactor = (mfxU16)pInParams->DenoiseLevel;
3133 }
3134
3135 if (pInParams->DetailLevel != -1)
3136 {
3137 auto detail = m_mfxVppParams.AddExtBuffer<mfxExtVPPDetail>();
3138 detail->DetailFactor = (mfxU16)pInParams->DetailLevel;
3139 }
3140
3141 if (pInParams->FRCAlgorithm)
3142 {
3143 auto frc = m_mfxVppParams.AddExtBuffer<mfxExtVPPFrameRateConversion>();
3144 frc->Algorithm = pInParams->FRCAlgorithm;
3145 }
3146
3147 if (pInParams->bEnableDeinterlacing && pInParams->DeinterlacingMode)
3148 {
3149 auto di = m_mfxVppParams.AddExtBuffer<mfxExtVPPDeinterlacing>();
3150 di->Mode = pInParams->DeinterlacingMode;
3151 }
3152
3153 //--- Field Copy Mode
3154 if (pInParams->fieldProcessingMode)
3155 {
3156 auto fieldProc = m_mfxVppParams.AddExtBuffer<mfxExtVPPFieldProcessing>();
3157
3158 //--- To check first is we do copy frame of field
3159 fieldProc->Mode = (mfxU16) (pInParams->fieldProcessingMode==FC_FR2FR ?
3160 MFX_VPP_COPY_FRAME :
3161 MFX_VPP_COPY_FIELD);
3162
3163 fieldProc->InField = (mfxU16) ((pInParams->fieldProcessingMode==FC_T2T || pInParams->fieldProcessingMode==FC_T2B) ?
3164 MFX_PICSTRUCT_FIELD_TFF :
3165 MFX_PICSTRUCT_FIELD_BFF);
3166
3167 fieldProc->OutField = (mfxU16) ((pInParams->fieldProcessingMode== FC_T2T || pInParams->fieldProcessingMode==FC_B2T) ?
3168 MFX_PICSTRUCT_FIELD_TFF :
3169 MFX_PICSTRUCT_FIELD_BFF);
3170 }
3171
3172 if (pInParams->ScalingMode)
3173 {
3174 auto par = m_mfxVppParams.AddExtBuffer<mfxExtVPPScaling>();
3175 par->ScalingMode = pInParams->ScalingMode;
3176 }
3177
3178 if (enhFilterCount)
3179 {
3180 auto doUse = m_mfxVppParams.AddExtBuffer<mfxExtVPPDoUse>();
3181 doUse->NumAlg = enhFilterCount;
3182 doUse->AlgList = m_tabDoUseAlg;
3183 }
3184
3185 #ifdef ENABLE_MCTF
3186 // would it be more efficienct to get a pointer?
3187 m_MctfRTParams = pInParams->mctfParam.rtParams;
3188 m_MctfRTParams.Restart();
3189 #endif
3190
3191 return MFX_ERR_NONE;
3192
3193 } //mfxStatus CTranscodingPipeline::InitMfxVppParams(sInputParams *pInParams)
3194
InitPluginMfxParams(sInputParams * pInParams)3195 mfxStatus CTranscodingPipeline::InitPluginMfxParams(sInputParams *pInParams)
3196 {
3197 MSDK_CHECK_POINTER(pInParams, MFX_ERR_NULL_PTR);
3198
3199 mfxU16 parentPattern = m_bIsVpp ? m_mfxVppParams.IOPattern : m_mfxDecParams.IOPattern;
3200 mfxU16 InPatternFromParent = (mfxU16)((MFX_IOPATTERN_OUT_VIDEO_MEMORY & parentPattern) ?
3201 MFX_IOPATTERN_IN_VIDEO_MEMORY : MFX_IOPATTERN_IN_SYSTEM_MEMORY);
3202
3203 // set memory pattern
3204 if (m_bUseOpaqueMemory)
3205 m_mfxPluginParams.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY|MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
3206 else if (pInParams->bForceSysMem || (MFX_IMPL_SOFTWARE == pInParams->libType))
3207 m_mfxPluginParams.IOPattern = (mfxU16)(InPatternFromParent|MFX_IOPATTERN_OUT_SYSTEM_MEMORY);
3208 else
3209 m_mfxPluginParams.IOPattern = (mfxU16)(InPatternFromParent|MFX_IOPATTERN_OUT_VIDEO_MEMORY);
3210
3211 m_mfxPluginParams.AsyncDepth = m_AsyncDepth;
3212
3213 // input frame info
3214 if (m_bIsVpp)
3215 {
3216 MSDK_MEMCPY_VAR(m_mfxPluginParams.vpp.In, &m_mfxVppParams.vpp.Out, sizeof(mfxFrameInfo));
3217 }
3218 else
3219 {
3220 m_mfxPluginParams.vpp.In = GetFrameInfo(m_mfxDecParams);
3221 }
3222
3223 // fill output frame info
3224 // in case of rotation plugin sample output frameinfo is same as input
3225 MSDK_MEMCPY_VAR(m_mfxPluginParams.vpp.Out, &m_mfxPluginParams.vpp.In, sizeof(mfxFrameInfo));
3226
3227 // configure and attach external parameters
3228 if (m_bUseOpaqueMemory)
3229 m_mfxPluginParams.AddExtBuffer<mfxExtOpaqueSurfaceAlloc>();
3230
3231 return MFX_ERR_NONE;
3232
3233 } //mfxStatus CTranscodingPipeline::InitMfxVppParams(sInputParams *pInParams)
3234
AllocFrames(mfxFrameAllocRequest * pRequest,bool isDecAlloc)3235 mfxStatus CTranscodingPipeline::AllocFrames(mfxFrameAllocRequest *pRequest, bool isDecAlloc)
3236 {
3237 mfxStatus sts = MFX_ERR_NONE;
3238
3239 mfxU16 nSurfNum = 0; // number of surfaces
3240 mfxU16 i;
3241
3242 nSurfNum = pRequest->NumFrameMin = pRequest->NumFrameSuggested;
3243 msdk_printf(MSDK_STRING("Pipeline surfaces number (%s): %d\n"), isDecAlloc ? MSDK_STRING("DecPool") : MSDK_STRING("EncPool"),nSurfNum);
3244
3245 mfxFrameAllocResponse *pResponse = isDecAlloc ? &m_mfxDecResponse : &m_mfxEncResponse;
3246
3247 // no actual memory is allocated if opaque memory type is used
3248 if (!m_bUseOpaqueMemory)
3249 {
3250 sts = m_pMFXAllocator->Alloc(m_pMFXAllocator->pthis, pRequest, pResponse);
3251 MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->Alloc failed");
3252 }
3253
3254 for (i = 0; i < nSurfNum; i++)
3255 {
3256 auto surface = std::unique_ptr<mfxFrameSurfaceWrap>(new mfxFrameSurfaceWrap);
3257 surface->Info = pRequest->Info;
3258
3259 if (m_rawInput)
3260 {
3261 sts = m_pMFXAllocator->Lock(m_pMFXAllocator->pthis, pResponse->mids[i], &(surface->Data));
3262 MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->Lock failed");
3263 }
3264 // no actual memory is allocated if opaque memory type is used (surface pointers and MemId field remain 0)
3265 else if (!m_bUseOpaqueMemory)
3266 {
3267 surface->Data.MemId = pResponse->mids[i];
3268 }
3269
3270 (isDecAlloc) ? m_pSurfaceDecPool.push_back(surface.get()) : m_pSurfaceEncPool.push_back(surface.get());
3271
3272 std::ignore = surface.release();
3273 }
3274
3275 (isDecAlloc) ? m_DecSurfaceType = pRequest->Type : m_EncSurfaceType = pRequest->Type;
3276
3277 return MFX_ERR_NONE;
3278
3279 } // mfxStatus CTranscodingPipeline::AllocFrames(Component* pComp, mfxFrameAllocResponse* pMfxResponse, mfxVideoParam* pMfxVideoParam)
3280
3281 //return true if correct
CheckAsyncDepth(mfxFrameAllocRequest & curReq,mfxU16 asyncDepth)3282 static bool CheckAsyncDepth(mfxFrameAllocRequest &curReq, mfxU16 asyncDepth)
3283 {
3284 return (curReq.NumFrameSuggested >= asyncDepth);
3285 }
3286
CorrectAsyncDepth(mfxFrameAllocRequest & curReq,mfxU16 asyncDepth)3287 static mfxStatus CorrectAsyncDepth(mfxFrameAllocRequest &curReq, mfxU16 asyncDepth)
3288 {
3289 mfxStatus sts = MFX_ERR_NONE;
3290 if (!CheckAsyncDepth(curReq, asyncDepth))
3291 {
3292 sts = MFX_ERR_MEMORY_ALLOC;
3293 }
3294 else
3295 {
3296 // The request holds summary of required surfaces numbers from 2 components and
3297 // asyncDepth is included twice. Here we patch surfaces number removing
3298 // one asyncDepth.
3299 curReq.NumFrameSuggested = curReq.NumFrameSuggested - asyncDepth;
3300 curReq.NumFrameMin = curReq.NumFrameSuggested;
3301 }
3302
3303 return sts;
3304 }
3305
SumAllocRequest(mfxFrameAllocRequest & curReq,mfxFrameAllocRequest & newReq)3306 static void SumAllocRequest(mfxFrameAllocRequest &curReq, mfxFrameAllocRequest &newReq)
3307 {
3308 curReq.NumFrameSuggested = curReq.NumFrameSuggested + newReq.NumFrameSuggested;
3309 curReq.NumFrameMin = curReq.NumFrameSuggested;
3310 curReq.Type = curReq.Type | newReq.Type;
3311
3312 if ((curReq.Type & MFX_MEMTYPE_SYSTEM_MEMORY) && ((curReq.Type & 0xf0) != MFX_MEMTYPE_SYSTEM_MEMORY))
3313 curReq.Type = (mfxU16)(curReq.Type & (~ MFX_MEMTYPE_SYSTEM_MEMORY));
3314 if ((curReq.Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) && ((curReq.Type & 0xf0) != MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET))
3315 curReq.Type = (mfxU16)(curReq.Type & (~MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET));
3316
3317 if (curReq.Info.Width == 0)
3318 {
3319 curReq.Info = newReq.Info;
3320 }
3321 else
3322 {
3323 curReq.Info.Width = curReq.Info.Width < newReq.Info.Width ? newReq.Info.Width : curReq.Info.Width ;
3324 curReq.Info.Height = curReq.Info.Height < newReq.Info.Height ? newReq.Info.Height : curReq.Info.Height ;
3325 }
3326 }
3327
AllocFrames()3328 mfxStatus CTranscodingPipeline::AllocFrames()
3329 {
3330 mfxStatus sts = MFX_ERR_NONE;
3331 bool bAddFrames = true; // correct shared pool between session
3332
3333 mfxFrameAllocRequest DecOut;
3334 mfxFrameAllocRequest VPPOut;
3335
3336 MSDK_ZERO_MEMORY(DecOut);
3337 MSDK_ZERO_MEMORY(VPPOut);
3338
3339 sts = CalculateNumberOfReqFrames(DecOut,VPPOut);
3340 MSDK_CHECK_STATUS(sts, "CalculateNumberOfReqFrames failed");
3341
3342 if (VPPOut.NumFrameSuggested)
3343 {
3344 if (bAddFrames)
3345 {
3346 SumAllocRequest(VPPOut, m_Request);
3347 bAddFrames = false;
3348 }
3349
3350 // Do not correct anything if we're using raw output - we'll need those surfaces for storing data for writer
3351 if(m_mfxEncParams.mfx.CodecId != MFX_CODEC_DUMP)
3352 {
3353 // In case of rendering enabled we need to add 1 additional surface for renderer
3354 if((m_nVPPCompEnable == VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode))
3355 {
3356 VPPOut.NumFrameSuggested++;
3357 VPPOut.NumFrameMin++;
3358 }
3359 sts = CorrectAsyncDepth(VPPOut, m_AsyncDepth);
3360 MSDK_CHECK_STATUS(sts, "CorrectAsyncDepth failed");
3361 /* WA for rendering: VPP should have at least 2 frames on output (for front & back buffer accordinally) */
3362 if ((VPPOut.NumFrameSuggested <= 1) || (VPPOut.NumFrameMin <= 1))
3363 {
3364 VPPOut.NumFrameSuggested = 2;
3365 VPPOut.NumFrameMin = 2;
3366 }
3367 }
3368
3369 #ifdef LIBVA_SUPPORT
3370 if (((m_nVPPCompEnable == VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode)) &&
3371 ((m_libvaBackend == MFX_LIBVA_DRM_MODESET) ||
3372 #if defined(X11_DRI3_SUPPORT)
3373 (m_libvaBackend == MFX_LIBVA_X11) ||
3374 #endif // X11_DRI3_SUPPORT
3375 (m_libvaBackend == MFX_LIBVA_WAYLAND)))
3376 {
3377 VPPOut.Type |= MFX_MEMTYPE_EXPORT_FRAME;
3378 }
3379 #endif
3380 sts = AllocFrames(&VPPOut, false);
3381 MSDK_CHECK_STATUS(sts, "AllocFrames failed");
3382 }
3383
3384 if (DecOut.NumFrameSuggested)
3385 {
3386 if (bAddFrames)
3387 {
3388 SumAllocRequest(DecOut, m_Request);
3389 bAddFrames = false;
3390 }
3391
3392 if (m_bDecodeEnable)
3393 {
3394 if(0 == m_nVPPCompEnable && m_mfxEncParams.mfx.CodecId != MFX_CODEC_DUMP)
3395 {
3396 //--- Make correction to number of surfaces only if composition is not enabled. In case of composition we need all the surfaces QueryIOSurf has requested to pass them to another session's VPP
3397 // In other inter-session cases, other sessions request additional surfaces using additional calls to AllocFrames
3398 sts = CorrectAsyncDepth(DecOut, m_AsyncDepth);
3399 MSDK_CHECK_STATUS(sts, "CorrectAsyncDepth failed");
3400 }
3401
3402 // AllocId just opaque handle which allow separate decoder requests in case of VPP Composition with external allocator
3403 static mfxU32 mark_alloc = 0;
3404 m_mfxDecParams.AllocId = mark_alloc;
3405 DecOut.AllocId = mark_alloc;
3406 if(m_nVPPCompEnable) // WORKAROUND: Remove this if clause after problem with AllocID is fixed in library (mark_alloc++ should be left here)
3407 {
3408 mark_alloc++;
3409 }
3410
3411 if ((DecOut.NumFrameSuggested <= 1) || (DecOut.NumFrameMin <= 1))
3412 {
3413 DecOut.NumFrameSuggested = 2;
3414 DecOut.NumFrameMin = 2;
3415 }
3416
3417 sts = AllocFrames(&DecOut, true);
3418 MSDK_CHECK_STATUS(sts, "AllocFrames failed");
3419 sts = CorrectPreEncAuxPool((VPPOut.NumFrameSuggested ? VPPOut.NumFrameSuggested : DecOut.NumFrameSuggested) + m_AsyncDepth);
3420 MSDK_CHECK_STATUS(sts, "CorrectPreEncAuxPool failed");
3421 sts = AllocPreEncAuxPool();
3422 MSDK_CHECK_STATUS(sts, "AllocPreEncAuxPool failed");
3423 }
3424 else if((m_nVPPCompEnable==VppComp || m_nVPPCompEnable==VppCompOnly || m_nVPPCompEnable==VppCompOnlyEncode) && m_bUseOpaqueMemory)
3425 {
3426 //--- N->1 case, allocating empty pool for opaque only
3427 sts = AllocFrames(&DecOut, true);
3428 MSDK_CHECK_STATUS(sts, "AllocFrames failed");
3429 }
3430 else
3431 {
3432 if ((m_pParentPipeline) &&
3433 (0 == m_nVPPCompEnable) /* case if 1_to_N */)
3434 {
3435 m_pParentPipeline->CorrectNumberOfAllocatedFrames(&DecOut);
3436 sts = m_pParentPipeline->CorrectPreEncAuxPool(VPPOut.NumFrameSuggested + DecOut.NumFrameSuggested + m_AsyncDepth);
3437 MSDK_CHECK_STATUS(sts, "m_pParentPipeline->CorrectPreEncAuxPool failed");
3438 }
3439 }
3440 }
3441
3442 return MFX_ERR_NONE;
3443 }
3444
CalculateNumberOfReqFrames(mfxFrameAllocRequest & pDecOut,mfxFrameAllocRequest & pVPPOut)3445 mfxStatus CTranscodingPipeline::CalculateNumberOfReqFrames(mfxFrameAllocRequest &pDecOut, mfxFrameAllocRequest &pVPPOut)
3446 {
3447 mfxStatus sts = MFX_ERR_NONE;
3448 mfxFrameAllocRequest *pSumRequest = &pDecOut;
3449
3450 memset(&pDecOut,0,sizeof(pDecOut));
3451 memset(&pVPPOut,0,sizeof(pVPPOut));
3452
3453 mfxFrameAllocRequest DecRequest;
3454 MSDK_ZERO_MEMORY(DecRequest);
3455
3456 if (m_pmfxDEC.get())
3457 {
3458 sts = m_pmfxDEC.get()->QueryIOSurf(&m_mfxDecParams, &DecRequest);
3459 MSDK_CHECK_STATUS(sts, "m_pmfxDEC.get failed");
3460
3461 if (!CheckAsyncDepth(DecRequest, m_mfxDecParams.AsyncDepth))
3462 return MFX_ERR_MEMORY_ALLOC;
3463 SumAllocRequest(*pSumRequest, DecRequest);
3464 }
3465 else if (m_bUseOverlay)
3466 {
3467 // It takes 1 surface for overlay
3468 DecRequest.NumFrameMin = DecRequest.NumFrameSuggested = 1;
3469 DecRequest.Type = MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET | MFX_MEMTYPE_EXTERNAL_FRAME;
3470 DecRequest.Info = GetFrameInfo(m_mfxDecParams);
3471 SumAllocRequest(*pSumRequest, DecRequest);
3472 }
3473
3474 if (m_pmfxVPP.get())
3475 {
3476 mfxFrameAllocRequest VppRequest[2];
3477
3478 MSDK_ZERO_MEMORY(VppRequest);
3479 if (m_bIsPlugin && m_bIsVpp)
3480 {
3481 sts = m_pmfxVPP.get()->QueryIOSurfMulti(&m_mfxPluginParams, &(VppRequest[0]), &m_mfxVppParams);
3482 if (!CheckAsyncDepth(VppRequest[0], m_mfxPluginParams.AsyncDepth) ||
3483 !CheckAsyncDepth(VppRequest[1], m_mfxPluginParams.AsyncDepth) ||
3484 !CheckAsyncDepth(VppRequest[0], m_mfxVppParams.AsyncDepth) ||
3485 !CheckAsyncDepth(VppRequest[1], m_mfxVppParams.AsyncDepth))
3486 return MFX_ERR_MEMORY_ALLOC;
3487 }
3488 else if (m_bIsPlugin)
3489 {
3490 sts = m_pmfxVPP.get()->QueryIOSurf(&m_mfxPluginParams, &(VppRequest[0]));
3491 if (!CheckAsyncDepth(VppRequest[0], m_mfxPluginParams.AsyncDepth) ||
3492 !CheckAsyncDepth(VppRequest[1], m_mfxPluginParams.AsyncDepth))
3493 return MFX_ERR_MEMORY_ALLOC;
3494 }
3495 else
3496 {
3497 sts = m_pmfxVPP.get()->QueryIOSurf(&m_mfxVppParams, &(VppRequest[0]));
3498 if (!CheckAsyncDepth(VppRequest[0], m_mfxVppParams.AsyncDepth) ||
3499 !CheckAsyncDepth(VppRequest[1], m_mfxVppParams.AsyncDepth))
3500 return MFX_ERR_MEMORY_ALLOC;
3501 }
3502
3503 MSDK_CHECK_STATUS(sts, "m_pmfxVPP.get()->QueryIOSurf failed");
3504
3505 SumAllocRequest(*pSumRequest, VppRequest[0]);
3506 pSumRequest = &pVPPOut;
3507 SumAllocRequest(*pSumRequest, VppRequest[1]);
3508 }
3509 if (m_pmfxPreENC.get())
3510 {
3511 mfxFrameAllocRequest PreEncRequest;
3512
3513 MSDK_ZERO_MEMORY(PreEncRequest);
3514 sts = m_pmfxPreENC.get()->QueryIOSurf(&m_mfxPreEncParams, &PreEncRequest);
3515 MSDK_CHECK_STATUS(sts, "m_pmfxPreENC.get()->QueryIOSurf failed");
3516
3517 if (!CheckAsyncDepth(PreEncRequest, m_mfxPreEncParams.AsyncDepth))
3518 return MFX_ERR_MEMORY_ALLOC;
3519 SumAllocRequest(*pSumRequest, PreEncRequest);
3520 }
3521 if (m_pmfxENC.get())
3522 {
3523 mfxFrameAllocRequest EncRequest;
3524
3525 MSDK_ZERO_MEMORY(EncRequest);
3526
3527 sts = m_pmfxENC.get()->QueryIOSurf(&m_mfxEncParams, &EncRequest);
3528 MSDK_CHECK_STATUS(sts, "m_pmfxENC.get()->QueryIOSurf failed");
3529
3530 if (!CheckAsyncDepth(EncRequest, m_mfxEncParams.AsyncDepth))
3531 return MFX_ERR_MEMORY_ALLOC;
3532 SumAllocRequest(*pSumRequest, EncRequest);
3533 }
3534
3535 if(!pSumRequest->Type && m_pmfxDEC.get())
3536 {
3537 //--- If noone has set type to VPP request type yet, set it now basing on decoder request type
3538 pSumRequest->Type = MFX_MEMTYPE_BASE(DecRequest.Type) | MFX_MEMTYPE_FROM_VPPOUT;
3539 }
3540
3541 return MFX_ERR_NONE;
3542 }
CorrectNumberOfAllocatedFrames(mfxFrameAllocRequest * pNewReq)3543 void CTranscodingPipeline::CorrectNumberOfAllocatedFrames(mfxFrameAllocRequest *pNewReq)
3544 {
3545 if(shouldUseGreedyFormula)
3546 {
3547 m_Request.NumFrameSuggested+=pNewReq->NumFrameSuggested;
3548 }
3549 else
3550 {
3551 m_Request.NumFrameSuggested = std::max(m_Request.NumFrameSuggested,pNewReq->NumFrameSuggested);
3552 }
3553
3554 m_Request.NumFrameMin = m_Request.NumFrameSuggested;
3555 m_Request.Type = m_Request.Type | pNewReq->Type;
3556
3557 if ((m_Request.Type & MFX_MEMTYPE_SYSTEM_MEMORY) && ((m_Request.Type & 0xf0) != MFX_MEMTYPE_SYSTEM_MEMORY))
3558 m_Request.Type = (mfxU16)(m_Request.Type & (~ MFX_MEMTYPE_SYSTEM_MEMORY));
3559 if ((m_Request.Type & MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET) && ((m_Request.Type & 0xf0) != MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET))
3560 m_Request.Type = (mfxU16)(m_Request.Type & (~ MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET));
3561
3562 if (m_Request.Info.Width == 0)
3563 {
3564 m_Request.Info = pNewReq->Info;
3565 }
3566 else
3567 {
3568 m_Request.Info.Width = m_Request.Info.Width < pNewReq->Info.Width ? pNewReq->Info.Width : m_Request.Info.Width ;
3569 m_Request.Info.Height = m_Request.Info.Height < pNewReq->Info.Height ? pNewReq->Info.Height : m_Request.Info.Height ;
3570 }
3571 }
3572
InitOpaqueAllocBuffers()3573 mfxStatus CTranscodingPipeline::InitOpaqueAllocBuffers()
3574 {
3575 auto decOpaq = m_mfxDecParams.AddExtBuffer<mfxExtOpaqueSurfaceAlloc>();
3576 auto vppOpaq = m_mfxVppParams.AddExtBuffer<mfxExtOpaqueSurfaceAlloc>();
3577 auto encOpaq = m_mfxEncParams.AddExtBuffer<mfxExtOpaqueSurfaceAlloc>();
3578 auto plgOpaq = m_mfxPluginParams.AddExtBuffer<mfxExtOpaqueSurfaceAlloc>();
3579 auto preencOpaq = m_mfxPreEncParams.AddExtBuffer<mfxExtOpaqueSurfaceAlloc>();
3580
3581 if (m_pmfxDEC.get() ||
3582 ((m_nVPPCompEnable == VppComp || m_nVPPCompEnable == VppCompOnly || m_nVPPCompEnable == VppCompOnlyEncode) && m_pSurfaceDecPool.size()))
3583 {
3584 decOpaq->Out.Surfaces = m_pSurfaceDecPool.data();
3585 decOpaq->Out.NumSurface = (mfxU16)m_pSurfaceDecPool.size();
3586
3587 if (m_DecSurfaceType & MFX_MEMTYPE_FROM_VPPOUT)
3588 decOpaq->Out.Type = (mfxU16)(MFX_MEMTYPE_BASE(m_DecSurfaceType) | MFX_MEMTYPE_FROM_VPPOUT);
3589 else
3590 decOpaq->Out.Type = (mfxU16)(MFX_MEMTYPE_BASE(m_DecSurfaceType) | MFX_MEMTYPE_FROM_DECODE);
3591 }
3592 else
3593 {
3594 // if no decoder in the pipeline we need to query OpaqueAlloc structure from parent sink pipeline
3595 *decOpaq = m_pParentPipeline->GetDecOpaqueAlloc();
3596 }
3597
3598 if (m_pmfxVPP.get())
3599 {
3600 encOpaq->In.Surfaces = m_pSurfaceEncPool.data();
3601 encOpaq->In.NumSurface = (mfxU16)m_pSurfaceEncPool.size();
3602 encOpaq->In.Type = (mfxU16)(MFX_MEMTYPE_BASE(m_EncSurfaceType) | MFX_MEMTYPE_FROM_ENCODE);
3603
3604 // decode will be connected with either VPP or Plugin
3605 if (m_bIsVpp)
3606 {
3607 vppOpaq->In = decOpaq->Out;
3608 }
3609 else if (m_bIsPlugin)
3610 {
3611 plgOpaq->In = decOpaq->Out;
3612 }
3613 else
3614 return MFX_ERR_UNSUPPORTED;
3615
3616 // encode will be connected with either Plugin or VPP
3617 if (m_bIsPlugin)
3618 plgOpaq->Out = encOpaq->In;
3619 else if (m_bIsVpp)
3620 vppOpaq->Out = encOpaq->In;
3621 else
3622 return MFX_ERR_UNSUPPORTED;
3623 }
3624 else if (m_pmfxENC.get() || m_pmfxPreENC.get())
3625 {
3626 encOpaq->In = decOpaq->Out;
3627 }
3628 if (m_pmfxPreENC.get())
3629 {
3630 preencOpaq->In = encOpaq->In;
3631 }
3632
3633 return MFX_ERR_NONE;
3634 }
3635
FreeFrames()3636 void CTranscodingPipeline::FreeFrames()
3637 {
3638 std::for_each(m_pSurfaceDecPool.begin(), m_pSurfaceDecPool.end(), [](mfxFrameSurface1* s)
3639 { auto surface = static_cast<mfxFrameSurfaceWrap*>(s); delete surface; });
3640 m_pSurfaceDecPool.clear();
3641
3642 std::for_each(m_pSurfaceEncPool.begin(), m_pSurfaceEncPool.end(), [](mfxFrameSurface1* s)
3643 { auto surface = static_cast<mfxFrameSurfaceWrap*>(s); delete surface; });
3644 m_pSurfaceEncPool.clear();
3645
3646 if (m_pMFXAllocator && !m_bUseOpaqueMemory)
3647 {
3648 m_pMFXAllocator->Free(m_pMFXAllocator->pthis, &m_mfxEncResponse);
3649 m_pMFXAllocator->Free(m_pMFXAllocator->pthis, &m_mfxDecResponse);
3650 }
3651 } // CTranscodingPipeline::FreeFrames()
3652
Init(sInputParams * pParams,MFXFrameAllocator * pMFXAllocator,void * hdl,CTranscodingPipeline * pParentPipeline,SafetySurfaceBuffer * pBuffer,FileBitstreamProcessor * pBSProc)3653 mfxStatus CTranscodingPipeline::Init(sInputParams *pParams,
3654 MFXFrameAllocator *pMFXAllocator,
3655 void* hdl,
3656 CTranscodingPipeline *pParentPipeline,
3657 SafetySurfaceBuffer *pBuffer,
3658 FileBitstreamProcessor *pBSProc)
3659 {
3660 MSDK_CHECK_POINTER(pParams, MFX_ERR_NULL_PTR);
3661 MSDK_CHECK_POINTER(pMFXAllocator, MFX_ERR_NULL_PTR);
3662 MSDK_CHECK_POINTER(pBSProc, MFX_ERR_NULL_PTR);
3663 mfxStatus sts = MFX_ERR_NONE;
3664 m_MaxFramesForTranscode = pParams->MaxFrameNumber;
3665 // if no number of frames for a particular session is undefined, default
3666 // value is 0xFFFFFFFF. Thus, use it as a marker to assign parent
3667 // MaxFramesForTranscode to m_MaxFramesForTranscode
3668 if(pParentPipeline && (0xFFFFFFFF == m_MaxFramesForTranscode) && pParentPipeline->m_MaxFramesForTranscode)
3669 m_MaxFramesForTranscode = pParentPipeline->m_MaxFramesForTranscode;
3670
3671 // use external allocator
3672 m_pMFXAllocator = pMFXAllocator;
3673 m_pBSProcessor = pBSProc;
3674 m_hdl = hdl;
3675
3676 m_pParentPipeline = pParentPipeline;
3677 shouldUseGreedyFormula = pParams->shouldUseGreedyFormula;
3678
3679 m_nTimeout = pParams->nTimeout;
3680
3681 m_AsyncDepth = (0 == pParams->nAsyncDepth)? 1: pParams->nAsyncDepth;
3682 m_FrameNumberPreference = pParams->FrameNumberPreference;
3683 m_numEncoders = 0;
3684 m_bUseOverlay = pParams->DecodeId == MFX_CODEC_RGB4 ? true : false;
3685 m_bRobustFlag = pParams->bRobustFlag;
3686 m_bSoftGpuHangRecovery = pParams->bSoftRobustFlag;
3687 m_nRotationAngle = pParams->nRotationAngle;
3688 m_sGenericPluginPath = pParams->strVPPPluginDLLPath;
3689 m_decoderPluginParams = pParams->decoderPluginParams;
3690 m_encoderPluginParams = pParams->encoderPluginParams;
3691
3692 m_encoderFourCC = pParams->EncoderFourCC;
3693
3694 m_rawInput = pParams->rawInput;
3695
3696 m_bExtMBQP = pParams->bExtMBQP;
3697 m_bROIasQPMAP = pParams->bROIasQPMAP;
3698
3699 #if MFX_VERSION >= 1022
3700 m_ROIData = pParams->m_ROIData;
3701 #endif //MFX_VERSION >= 1022
3702
3703 statisticsWindowSize = pParams->statisticsWindowSize;
3704 if (statisticsWindowSize > m_MaxFramesForTranscode)
3705 statisticsWindowSize = m_MaxFramesForTranscode;
3706
3707 m_strMfxParamsDumpFile.assign(pParams->strMfxParamsDumpFile);
3708
3709 if (pParams->statisticsLogFile)
3710 {
3711 //same log file for intput/output
3712 inputStatistics.SetOutputFile(pParams->statisticsLogFile);
3713 outputStatistics.SetOutputFile(pParams->statisticsLogFile);
3714 }
3715
3716 if(!pParams->DumpLogFileName.empty())
3717 {
3718 inputStatistics.SetDumpName((pParams->DumpLogFileName + MSDK_STRING("_input")).c_str());
3719 outputStatistics.SetDumpName((pParams->DumpLogFileName + MSDK_STRING("_output")).c_str());
3720 }
3721
3722 // if no statistic-window is passed but overall stat-log exist:
3723 // is requested, set statisticsWindowSize to m_MaxFramesForTranscode
3724 if ((pParams->statisticsLogFile || !pParams->DumpLogFileName.empty()) &&
3725 0 == statisticsWindowSize)
3726 statisticsWindowSize = m_MaxFramesForTranscode;
3727
3728 if (m_bEncodeEnable)
3729 {
3730 m_pBSStore.reset(new ExtendedBSStore(m_AsyncDepth));
3731 }
3732
3733 // Determine processing mode
3734 switch(pParams->eMode)
3735 {
3736 case Native:
3737 break;
3738 case Sink:
3739 if ((VppComp == pParams->eModeExt) || (VppCompOnly == pParams->eModeExt))
3740 {
3741 if ((NULL != pParentPipeline) && (NULL != pParentPipeline->m_pMFXAllocator))
3742 m_pMFXAllocator = pParentPipeline->m_pMFXAllocator;
3743 }
3744
3745 m_bEncodeEnable = false; // decode only
3746 break;
3747 case Source:
3748 // for heterogeneous pipeline use parent allocator
3749 MSDK_CHECK_POINTER(pParentPipeline, MFX_ERR_NULL_PTR);
3750 m_pMFXAllocator = pParentPipeline->m_pMFXAllocator;
3751 m_bDecodeEnable = false; // encode only
3752 /**/
3753 if ((pParams->m_hwdev != NULL) && (VppCompOnly == pParams->eModeExt))
3754 {
3755 #if defined(_WIN32) || defined(_WIN64)
3756 m_hwdev4Rendering = new CDecodeD3DRender;
3757 m_hwdev4Rendering->SetHWDevice(pParams->m_hwdev);
3758
3759 sWindowParams RenderParam;
3760
3761 memset(&RenderParam, 0, sizeof(sWindowParams));
3762
3763 RenderParam.lpWindowName = MSDK_STRING("sample_multi_transcode");
3764 RenderParam.nx = 0;
3765 RenderParam.ny = 0;
3766 RenderParam.nWidth = pParams->nDstWidth;
3767 RenderParam.nHeight = pParams->nDstHeight;
3768 RenderParam.ncell = 0;
3769 RenderParam.nAdapter = 0;
3770
3771 RenderParam.lpClassName = MSDK_STRING("Render Window Class");
3772 RenderParam.dwStyle = WS_OVERLAPPEDWINDOW;
3773 RenderParam.hWndParent = NULL;
3774 RenderParam.hMenu = NULL;
3775 RenderParam.hInstance = GetModuleHandle(NULL);
3776 RenderParam.lpParam = NULL;
3777 RenderParam.bFullScreen = TRUE;
3778
3779 m_hwdev4Rendering->Init(RenderParam);
3780 #else
3781 if(pParams->EncodeId)
3782 {
3783 m_nVPPCompEnable = VppCompOnlyEncode;
3784 }
3785 m_hwdev4Rendering = pParams->m_hwdev;
3786 #endif
3787 }
3788 break;
3789 default:
3790 // unknown mode
3791 return MFX_ERR_UNSUPPORTED;
3792 }
3793
3794 if ((VppComp == pParams->eModeExt) || (VppCompOnly == pParams->eModeExt))
3795 {
3796 if(m_nVPPCompEnable != VppCompOnlyEncode)
3797 m_nVPPCompEnable = pParams->eModeExt;
3798 }
3799
3800 #ifdef LIBVA_SUPPORT
3801 m_libvaBackend = pParams->libvaBackend;
3802 #endif
3803
3804 m_pBuffer = pBuffer;
3805
3806 // we set version to 1.0 and later we will query actual version of the library which will got leaded
3807 m_initPar.Version.Major = 1;
3808 m_initPar.Version.Minor = 0;
3809 m_initPar.Implementation = pParams->libType;
3810
3811 if (pParams->nThreadsNum)
3812 {
3813 auto threadsPar = m_initPar.AddExtBuffer<mfxExtThreadsParam>();
3814 threadsPar->NumThread = pParams->nThreadsNum;
3815 }
3816
3817 //--- GPU Copy settings
3818 m_initPar.GPUCopy = pParams->nGpuCopyMode;
3819
3820 // init session
3821 m_pmfxSession.reset(new MFXVideoSession);
3822
3823 // Initializing library
3824 sts = m_pmfxSession->InitEx(m_initPar);
3825 MSDK_CHECK_STATUS(sts, "m_pmfxSession->InitEx failed");
3826 // check the API version of actually loaded library
3827 sts = m_pmfxSession->QueryVersion(&m_Version);
3828 MSDK_CHECK_STATUS(sts, "m_pmfxSession->QueryVersion failed");
3829 // check the implementation version of actually loaded library
3830 sts = m_pmfxSession->QueryIMPL(&pParams->libType);
3831 MSDK_CHECK_STATUS(sts, "m_pmfxSession->QueryIMPL failed");
3832
3833 #if defined(_WIN32) || defined(_WIN64)
3834 if (MFX_CODEC_AV1 == pParams->DecodeId && MFX_IMPL_VIA_MASK(pParams->libType) == MFX_IMPL_VIA_D3D9)
3835 {
3836 sts = MFX_ERR_UNSUPPORTED;
3837 MSDK_CHECK_STATUS(sts, "AV1d have no DX9 support \n");
3838 }
3839 #endif
3840
3841 sts = CheckRequiredAPIVersion(m_Version, pParams);
3842 MSDK_CHECK_STATUS(sts, "CheckRequiredAPIVersion failed");
3843
3844 // common session settings
3845 mfxU32 version = MakeVersion(m_Version.Major, m_Version.Minor);
3846 if (version >= 1001)
3847 sts = m_pmfxSession->SetPriority(pParams->priority);
3848
3849 // opaque memory feature is available starting with API 1.3 and
3850 // can be used within 1 intra session or joined inter sessions only
3851 if (version >= 1003 &&
3852 (pParams->eMode == Native || pParams->bIsJoin) && !pParams->rawInput)
3853 {
3854 m_bUseOpaqueMemory = true;
3855 }
3856 if (!pParams->bUseOpaqueMemory || pParams->EncodeId == MFX_CODEC_DUMP) // Don't use opaque in case of yuv output or if it was specified explicitly
3857 m_bUseOpaqueMemory = false;
3858
3859 m_bIsInterOrJoined = pParams->eMode == Sink || pParams->eMode == Source || pParams->bIsJoin;
3860
3861 sts = SetAllocatorAndHandleIfRequired();
3862 MSDK_CHECK_STATUS(sts, "SetAllocatorAndHandleIfRequired failed");
3863
3864 // Joining sessions if required
3865 if (pParams->bIsJoin && pParentPipeline)
3866 {
3867 sts = pParentPipeline->Join(m_pmfxSession.get());
3868 MSDK_CHECK_STATUS(sts, "pParentPipeline->Join failed");
3869 m_bIsJoinSession = true;
3870 }
3871
3872 // Initialize pipeline components following downstream direction
3873 // Pre-init methods fill parameters and create components
3874
3875 if (!m_rawInput)
3876 {
3877 // Decode component initialization
3878 sts = DecodePreInit(pParams);
3879 if (MFX_ERR_MORE_DATA == sts)
3880 return sts;
3881 else
3882 MSDK_CHECK_STATUS(sts,"DecodePreInit failed");
3883 }
3884 else
3885 {
3886 m_mfxDecParams.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
3887 if (MFX_CODEC_I420 == pParams->DecodeId || MFX_CODEC_NV12 == pParams->DecodeId || MFX_CODEC_P010 == pParams->DecodeId)
3888 {
3889 m_mfxDecParams.mfx.FrameInfo.FourCC = FileFourCC2EncFourCC(pParams->DecodeId);
3890 m_mfxDecParams.mfx.FrameInfo.ChromaFormat = FourCCToChroma(pParams->DecoderFourCC);
3891 }
3892 else if (pParams->DecoderFourCC)
3893 {
3894 m_mfxDecParams.mfx.FrameInfo.FourCC = pParams->DecoderFourCC;
3895 }
3896 }
3897
3898 if (pParams->IsSourceMSB)
3899 {
3900 m_shouldUseShifted10BitVPP = true;
3901 m_shouldUseShifted10BitEnc = true;
3902 }
3903
3904 // VPP component initialization
3905 sts = VPPPreInit(pParams);
3906 MSDK_CHECK_STATUS(sts, "VPPPreInit failed");
3907
3908 // Adjusting encoding settings according to selected preset
3909 if (Sink != pParams->eMode)
3910 {
3911 mfxFrameInfo eInfo;
3912 FillFrameInfoForEncoding(eInfo, pParams);
3913 ModifyParamsUsingPresets(*pParams, ((double)eInfo.FrameRateExtN) / eInfo.FrameRateExtD, eInfo.Width, eInfo.Height);
3914 }
3915
3916 // LA component initialization
3917 sts = PreEncPreInit(pParams);
3918 MSDK_CHECK_STATUS(sts, "PreEncPreInit failed");
3919
3920 // Encode component initialization
3921 if ((m_nVPPCompEnable != VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode))
3922 {
3923 sts = EncodePreInit(pParams);
3924 MSDK_CHECK_STATUS(sts, "EncodePreInit failed");
3925 }
3926
3927 if ((pParams->eMode == Source) &&
3928 ((m_nVPPCompEnable == VppCompOnly) ||
3929 (m_nVPPCompEnable == VppCompOnlyEncode) ||
3930 (m_nVPPCompEnable == VppComp)) )
3931 {
3932 if ((0 == msdk_strncmp(MSDK_STRING("null_render"), pParams->strDumpVppCompFile, msdk_strlen(MSDK_STRING("null_render")))))
3933 m_vppCompDumpRenderMode = NULL_RENDER_VPP_COMP; // null_render case
3934 else if (0 != msdk_strlen(pParams->strDumpVppCompFile))
3935 {
3936 sts = m_dumpVppCompFileWriter.Init(pParams->strDumpVppCompFile, 0);
3937 MSDK_CHECK_STATUS(sts, "VPP COMP DUMP File Init failed");
3938 m_vppCompDumpRenderMode = DUMP_FILE_VPP_COMP;
3939 }
3940 }
3941
3942 // Frames allocation for all component
3943 if (Native == pParams->eMode)
3944 {
3945 sts = AllocFrames();
3946 MSDK_CHECK_STATUS(sts, "AllocFrames failed");
3947 }
3948 else if (Source == pParams->eMode)// need allocate frames only for VPP and Encode if VPP exist
3949 {
3950 if (!m_bDecodeEnable)
3951 {
3952 sts = AllocFrames();
3953 MSDK_CHECK_STATUS(sts, "AllocFrames failed");
3954 }
3955 }
3956
3957 isHEVCSW = AreGuidsEqual(pParams->decoderPluginParams.pluginGuid, MFX_PLUGINID_HEVCD_SW);
3958
3959 // if sink - suspended allocation
3960 if (Native != pParams->eMode)
3961 return sts;
3962
3963 // after surfaces arrays are allocated configure mfxOpaqueAlloc buffers to be passed to components' Inits
3964 if (m_bUseOpaqueMemory)
3965 {
3966 sts = InitOpaqueAllocBuffers();
3967 MSDK_CHECK_STATUS(sts, "InitOpaqueAllocBuffers failed");
3968 }
3969
3970 // Init decode
3971 if (m_pmfxDEC.get())
3972 {
3973 sts = m_pmfxDEC->Init(&m_mfxDecParams);
3974 MSDK_CHECK_STATUS(sts, "m_pmfxDEC->Init failed");
3975 }
3976
3977 // Init VPP
3978 if (m_pmfxVPP.get())
3979 {
3980 if (m_bIsPlugin && m_bIsVpp)
3981 sts = m_pmfxVPP->InitMulti(&m_mfxPluginParams, &m_mfxVppParams);
3982 else if (m_bIsPlugin)
3983 sts = m_pmfxVPP->Init(&m_mfxPluginParams);
3984 else
3985 sts = m_pmfxVPP->Init(&m_mfxVppParams);
3986 MSDK_CHECK_STATUS(sts, "m_pmfxVPP->Init failed");
3987
3988 if (MFX_WRN_PARTIAL_ACCELERATION == sts)
3989 {
3990 msdk_printf(MSDK_STRING("WARNING: partial acceleration\n"));
3991 MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
3992 }
3993 MSDK_CHECK_STATUS(sts, "m_pmfxVPP->Init failed");
3994 }
3995 // LA initialization
3996 if (m_pmfxPreENC.get())
3997 {
3998 sts = m_pmfxPreENC->Init(&m_mfxPreEncParams);
3999 MSDK_CHECK_STATUS(sts, "m_pmfxPreENC->Init failed");
4000 }
4001 // Init encode
4002 if (m_pmfxENC.get())
4003 {
4004 sts = m_pmfxENC->Init(&m_mfxEncParams);
4005 MSDK_CHECK_STATUS(sts, "m_pmfxENC->Init failed");
4006
4007 #if MFX_VERSION >= 1022
4008 if (pParams->bExtMBQP)
4009 {
4010 m_bUseQPMap = true;
4011 }
4012
4013 if(pParams->bROIasQPMAP)
4014 {
4015 mfxVideoParam enc_par;
4016 MSDK_ZERO_MEMORY(enc_par);
4017 mfxStatus sts1 = m_pmfxENC->GetVideoParam(&enc_par);
4018 MSDK_CHECK_STATUS(sts1, "m_pmfxENC->GetVideoParam failed");
4019
4020 if(enc_par.mfx.GopRefDist != 1)
4021 {
4022 printf("INFO: Sample implementation of ROI through MBQP map require B-frames to be disabled.\n");
4023 m_bUseQPMap = false;
4024 }
4025 else if(enc_par.mfx.RateControlMethod != MFX_RATECONTROL_CQP)
4026 {
4027 printf("INFO: MBQP map require ConstQP mode to operate.\n");
4028 m_bUseQPMap = false;
4029 }
4030 else
4031 {
4032 m_GOPSize = (enc_par.mfx.GopPicSize) ? enc_par.mfx.GopPicSize : 1;
4033 m_QPforI = enc_par.mfx.QPI;
4034 m_QPforP = enc_par.mfx.QPP;
4035 m_bUseQPMap = true;
4036 }
4037 }
4038 #endif //MFX_VERSION >= 1022
4039 }
4040
4041 // Dumping components configuration if required
4042 if (m_strMfxParamsDumpFile.size())
4043 {
4044 CParametersDumper::DumpLibraryConfiguration(m_strMfxParamsDumpFile, m_pmfxDEC.get(), m_pmfxVPP.get(), m_pmfxENC.get(), &m_mfxDecParams, &m_mfxVppParams, &m_mfxEncParams);
4045 }
4046
4047 m_bIsInit = true;
4048
4049 return sts;
4050 } //mfxStatus CTranscodingPipeline::Init(sInputParams *pParams)
4051
4052
CompleteInit()4053 mfxStatus CTranscodingPipeline::CompleteInit()
4054 {
4055 mfxStatus sts = MFX_ERR_NONE;
4056
4057 if (m_bIsInit)
4058 return MFX_ERR_NONE;
4059
4060 // need to allocate remaining frames
4061 if (m_bDecodeEnable)
4062 {
4063 sts = AllocFrames();
4064 MSDK_CHECK_STATUS(sts, "AllocFrames failed");
4065 LoadStaticSurface();
4066 MSDK_CHECK_STATUS(sts, "LoadStaticSurface failed");
4067 }
4068
4069 // after surfaces arrays are allocated configure mfxOpaqueAlloc buffers to be passed to components' Inits
4070 if (m_bUseOpaqueMemory)
4071 {
4072 sts = InitOpaqueAllocBuffers();
4073 MSDK_CHECK_STATUS(sts, "InitOpaqueAllocBuffers failed");
4074 }
4075
4076 // Init decode
4077 if (m_pmfxDEC.get())
4078 {
4079 sts = m_pmfxDEC->Init(&m_mfxDecParams);
4080 if (MFX_WRN_PARTIAL_ACCELERATION == sts)
4081 {
4082 msdk_printf(MSDK_STRING("WARNING: partial acceleration\n"));
4083 MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
4084 }
4085 MSDK_CHECK_STATUS(sts, "m_pmfxDEC->Init failed");
4086 }
4087
4088 // Init vpp
4089 if (m_pmfxVPP.get())
4090 {
4091 if (m_bIsPlugin && m_bIsVpp)
4092 sts = m_pmfxVPP->InitMulti(&m_mfxPluginParams, &m_mfxVppParams);
4093 else if (m_bIsPlugin)
4094 sts = m_pmfxVPP->Init(&m_mfxPluginParams);
4095 else
4096 sts = m_pmfxVPP->Init(&m_mfxVppParams);
4097 MSDK_CHECK_STATUS(sts, "m_pmfxVPP->Init failed");
4098 }
4099 // Pre init encode
4100 if (m_pmfxPreENC.get())
4101 {
4102 sts = m_pmfxPreENC->Init(&m_mfxPreEncParams);
4103 if (MFX_WRN_PARTIAL_ACCELERATION == sts)
4104 {
4105 msdk_printf(MSDK_STRING("WARNING: partial acceleration\n"));
4106 MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
4107 }
4108 MSDK_CHECK_STATUS(sts, "m_pmfxPreENC->Init failed");
4109 }
4110 // Init encode
4111 if (m_pmfxENC.get())
4112 {
4113 sts = m_pmfxENC->Init(&m_mfxEncParams);
4114 if (MFX_WRN_PARTIAL_ACCELERATION == sts)
4115 {
4116 msdk_printf(MSDK_STRING("WARNING: partial acceleration\n"));
4117 MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
4118 }
4119 MSDK_CHECK_STATUS(sts, "m_pmfxENC->Init failed");
4120 }
4121
4122 m_bIsInit = true;
4123
4124 return sts;
4125 } // mfxStatus CTranscodingPipeline::CompleteInit()
GetFreeSurface(bool isDec,mfxU64 timeout)4126 mfxFrameSurface1* CTranscodingPipeline::GetFreeSurface(bool isDec, mfxU64 timeout)
4127 {
4128 mfxFrameSurface1* pSurf = NULL;
4129
4130 CTimer t;
4131 t.Start();
4132 do
4133 {
4134 {
4135 std::lock_guard<std::mutex> lock(m_mStopSession);
4136 if (m_bForceStop)
4137 {
4138 msdk_printf(MSDK_STRING("WARNING: m_bForceStop is set, returning NULL ptr from GetFreeSurface\n"));
4139 break;
4140 }
4141 }
4142
4143 SurfPointersArray & workArray = isDec ? m_pSurfaceDecPool : m_pSurfaceEncPool;
4144
4145 for (mfxU32 i = 0; i < workArray.size(); i++)
4146 {
4147 if (!workArray[i]->Data.Locked)
4148 {
4149 pSurf = workArray[i];
4150 break;
4151 }
4152 }
4153 if (pSurf)
4154 {
4155 break;
4156 }
4157 else
4158 {
4159 MSDK_SLEEP(TIME_TO_SLEEP);
4160 }
4161 } while ( t.GetTime() < timeout / 1000 );
4162
4163 return pSurf;
4164 } // mfxFrameSurface1* CTranscodingPipeline::GetFreeSurface(bool isDec)
4165
GetFreeSurfacesCount(bool isDec)4166 mfxU32 CTranscodingPipeline::GetFreeSurfacesCount(bool isDec)
4167 {
4168 SurfPointersArray& workArray = isDec ? m_pSurfaceDecPool : m_pSurfaceEncPool;
4169 mfxU32 count=0;
4170 for (mfxU32 i = 0; i < workArray.size(); i++)
4171 {
4172 if (!workArray[i]->Data.Locked)
4173 {
4174 count++;
4175 }
4176 }
4177 return count;
4178 }
4179
4180
GetFreePreEncAuxBuffer()4181 PreEncAuxBuffer* CTranscodingPipeline::GetFreePreEncAuxBuffer()
4182 {
4183 for(mfxU32 i = 0; i < m_pPreEncAuxPool.size(); i++)
4184 {
4185 if (!m_pPreEncAuxPool[i].Locked)
4186 return &(m_pPreEncAuxPool[i]);
4187 }
4188 return NULL;
4189 }
4190
LockPreEncAuxBuffer(PreEncAuxBuffer * pBuff)4191 void CTranscodingPipeline::LockPreEncAuxBuffer(PreEncAuxBuffer* pBuff)
4192 {
4193 if (!pBuff) return;
4194 for (mfxU32 i=0; i < m_numEncoders; i++)
4195 {
4196 msdk_atomic_inc16(&pBuff->Locked);
4197 }
4198 }
4199
UnPreEncAuxBuffer(PreEncAuxBuffer * pBuff)4200 void CTranscodingPipeline::UnPreEncAuxBuffer(PreEncAuxBuffer* pBuff)
4201 {
4202 if (!pBuff) return;
4203 msdk_atomic_dec16(&pBuff->Locked);
4204 }
4205
GetNumFramesForReset()4206 mfxU32 CTranscodingPipeline::GetNumFramesForReset()
4207 {
4208 std::lock_guard<std::mutex> guard(m_mReset);
4209 return m_NumFramesForReset;
4210 }
4211
SetNumFramesForReset(mfxU32 nFrames)4212 void CTranscodingPipeline::SetNumFramesForReset(mfxU32 nFrames)
4213 {
4214 std::lock_guard<std::mutex> guard(m_mReset);
4215 m_NumFramesForReset = nFrames;
4216 }
4217
HandlePossibleGpuHang(mfxStatus & sts)4218 void CTranscodingPipeline::HandlePossibleGpuHang(mfxStatus & sts)
4219 {
4220 if (sts == MFX_ERR_GPU_HANG && m_bSoftGpuHangRecovery)
4221 {
4222 msdk_printf(MSDK_STRING("[WARNING] GPU hang happened. Inserting an IDR and continuing transcoding.\n"));
4223 m_bInsertIDR = true;
4224 for (BSList::iterator it = m_BSPool.begin(); it != m_BSPool.end(); it++)
4225 {
4226 (*it)->IsFree = true;
4227 (*it)->Bitstream.DataOffset = 0;
4228 (*it)->Bitstream.DataLength = 0;
4229 }
4230 m_BSPool.clear();
4231 sts = MFX_ERR_NONE;
4232 }
4233 }
4234
SetAllocatorAndHandleIfRequired()4235 mfxStatus CTranscodingPipeline::SetAllocatorAndHandleIfRequired()
4236 {
4237 mfxStatus sts = MFX_ERR_NONE;
4238 mfxIMPL impl = 0;
4239 m_pmfxSession->QueryIMPL(&impl);
4240
4241 mfxHandleType handleType = (mfxHandleType)0;
4242 bool bIsMustSetExternalHandle = 0;
4243
4244 if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl))
4245 {
4246 handleType = MFX_HANDLE_D3D11_DEVICE;
4247 bIsMustSetExternalHandle = false;
4248 }
4249 else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl))
4250 {
4251 handleType = MFX_HANDLE_D3D9_DEVICE_MANAGER;
4252 bIsMustSetExternalHandle = false;
4253 }
4254 #ifdef LIBVA_SUPPORT
4255 else if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl))
4256 {
4257 handleType = MFX_HANDLE_VA_DISPLAY;
4258 bIsMustSetExternalHandle = true;
4259 }
4260 #endif
4261
4262 if (m_hdl && (bIsMustSetExternalHandle || (m_bIsInterOrJoined || !m_bUseOpaqueMemory)))
4263 {
4264 sts = m_pmfxSession->SetHandle(handleType, m_hdl);
4265 MSDK_CHECK_STATUS(sts, "m_pmfxSession->SetHandle failed");
4266 }
4267
4268 // Media SDK session doesn't require external allocator if the application uses opaque memory
4269 if (!m_bUseOpaqueMemory)
4270 {
4271 sts = m_pmfxSession->SetFrameAllocator(m_pMFXAllocator);
4272 MSDK_CHECK_STATUS(sts, "m_pmfxSession->SetFrameAllocator failed");
4273 }
4274
4275 return sts;
4276 }
4277
LoadGenericPlugin()4278 mfxStatus CTranscodingPipeline::LoadGenericPlugin()
4279 {
4280 mfxStatus sts = MFX_ERR_NONE;
4281
4282 std::unique_ptr<MFXVideoVPPPlugin> pVPPPlugin(new MFXVideoVPPPlugin(*m_pmfxSession.get()));
4283 MSDK_CHECK_POINTER(pVPPPlugin.get(), MFX_ERR_NULL_PTR);
4284
4285 sts = pVPPPlugin->LoadDLL((msdk_char*)m_sGenericPluginPath.c_str());
4286 MSDK_CHECK_STATUS(sts, "pVPPPlugin->LoadDLL failed");
4287
4288 m_RotateParam.Angle = m_nRotationAngle;
4289 sts = pVPPPlugin->SetAuxParam(&m_RotateParam, sizeof(m_RotateParam));
4290 MSDK_CHECK_STATUS(sts, "pVPPPlugin->SetAuxParam failed");
4291
4292 if (!m_bUseOpaqueMemory)
4293 {
4294 sts = pVPPPlugin->SetFrameAllocator(m_pMFXAllocator);
4295 MSDK_CHECK_STATUS(sts, "pVPPPlugin->SetFrameAllocator failed");
4296 }
4297
4298 m_pmfxVPP.reset(pVPPPlugin.release());
4299 return MFX_ERR_NONE;
4300 }
4301
GetRobustFlag()4302 size_t CTranscodingPipeline::GetRobustFlag()
4303 {
4304 return m_bRobustFlag;
4305 }
4306
Close()4307 void CTranscodingPipeline::Close()
4308 {
4309 if (m_pmfxDEC.get())
4310 m_pmfxDEC->Close();
4311
4312 if (m_pmfxENC.get())
4313 m_pmfxENC->Close();
4314
4315 if (m_pmfxVPP.get())
4316 m_pmfxVPP->Close();
4317
4318 if (m_pUserDecoderPlugin.get())
4319 m_pUserDecoderPlugin.reset();
4320
4321 if (m_pUserEncoderPlugin.get())
4322 m_pUserEncoderPlugin.reset();
4323
4324 if (m_pUserEncPlugin.get())
4325 m_pUserEncPlugin.reset();
4326
4327
4328 FreeVppDoNotUse();
4329 FreeMVCSeqDesc();
4330 FreePreEncAuxPool();
4331
4332 mfxExtVPPComposite* vppCompPar = m_mfxVppParams;
4333 if (vppCompPar && vppCompPar->InputStream)
4334 free(vppCompPar->InputStream);
4335
4336 if (m_bIsJoinSession)
4337 {
4338 //m_pmfxSession->DisjoinSession();
4339 m_bIsJoinSession = false;
4340 }
4341
4342 //Destroy renderer
4343 #if defined(_WIN32) || defined(_WIN64)
4344 if(m_hwdev4Rendering)
4345 {
4346 delete m_hwdev4Rendering;
4347 m_hwdev4Rendering=NULL;
4348 }
4349 #endif
4350
4351 // free allocated surfaces AFTER closing components
4352 FreeFrames();
4353
4354 m_bIsInit = false;
4355
4356 } // void CTranscodingPipeline::Close()
4357
Reset()4358 mfxStatus CTranscodingPipeline::Reset()
4359 {
4360 mfxStatus sts = MFX_ERR_NONE;
4361 bool isDec = m_pmfxDEC.get() ? true : false,
4362 isEnc = m_pmfxENC.get() ? true : false,
4363 isVPP = m_pmfxVPP.get() ? true : false,
4364 isPreEnc = m_pmfxPreENC.get() ? true : false,
4365 isGenericPLugin = m_nRotationAngle ? true : false,
4366 isDecoderPlugin = m_pUserDecoderPlugin.get() ? true : false,
4367 isEncoderPlugin = m_pUserEncoderPlugin.get() ? true : false,
4368 isPreEncPlugin = m_pUserEncPlugin.get() ? true : false;
4369
4370 // Close components being used
4371 if (isDec)
4372 {
4373 m_pmfxDEC->Close();
4374 m_pmfxDEC.reset();
4375 }
4376
4377 if (isVPP)
4378 {
4379 m_pmfxVPP->Close();
4380 m_pmfxVPP.reset();
4381 }
4382
4383 if (isPreEnc)
4384 {
4385 m_pmfxPreENC->Close();
4386 m_pmfxPreENC.reset();
4387 }
4388
4389 if (isEnc)
4390 {
4391 m_pmfxENC->Close();
4392 m_pmfxENC.reset();
4393 }
4394
4395 if (isDecoderPlugin)
4396 {
4397 m_pUserDecoderPlugin.reset();
4398 m_pUserDecoderModule.reset();
4399 }
4400
4401 if (isEncoderPlugin)
4402 {
4403 m_pUserEncoderPlugin.reset();
4404 m_pUserEncoderModule.reset();
4405 }
4406 m_pmfxSession->Close();
4407 m_pmfxSession.reset();
4408
4409 m_pmfxSession.reset(new MFXVideoSession());
4410 sts = m_pmfxSession->InitEx(m_initPar);
4411 MSDK_CHECK_STATUS(sts, "m_pmfxSession->InitEx failed");
4412
4413 // Release dec and enc surface pools
4414 for (size_t i = 0; i < m_pSurfaceDecPool.size(); i++)
4415 {
4416 m_pSurfaceDecPool[i]->Data.Locked = 0;
4417 }
4418 for (size_t i = 0; i < m_pSurfaceEncPool.size(); i++)
4419 {
4420 m_pSurfaceEncPool[i]->Data.Locked = 0;
4421 }
4422
4423 // Release all safety buffers
4424 SafetySurfaceBuffer* sptr = m_pBuffer;
4425 while (sptr)
4426 {
4427 sptr->ReleaseSurfaceAll();
4428 sptr = sptr->m_pNext;
4429 }
4430
4431 // Release output bitstram pools
4432 m_BSPool.clear();
4433 m_pBSStore->ReleaseAll();
4434 m_pBSStore->FlushAll();
4435
4436 // Load external decoder plugin
4437 if (isDecoderPlugin)
4438 {
4439 if (m_decoderPluginParams.type == MFX_PLUGINLOAD_TYPE_FILE && msdk_strnlen(m_decoderPluginParams.strPluginPath, sizeof(m_decoderPluginParams.strPluginPath)))
4440 {
4441 m_pUserDecoderModule.reset(new MFXVideoUSER(*m_pmfxSession.get()));
4442 m_pUserDecoderPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_DECODE, *m_pmfxSession.get(), m_decoderPluginParams.pluginGuid, 1, m_decoderPluginParams.strPluginPath, (mfxU32)msdk_strnlen(m_decoderPluginParams.strPluginPath, sizeof(m_decoderPluginParams.strPluginPath))));
4443 if (m_pUserDecoderPlugin.get() == NULL) sts = MFX_ERR_UNSUPPORTED;
4444 }
4445 else
4446 {
4447 if (AreGuidsEqual(m_decoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL))
4448 {
4449 m_decoderPluginParams.pluginGuid = msdkGetPluginUID(m_initPar.Implementation, MSDK_VDECODE, m_mfxDecParams.mfx.CodecId);
4450 }
4451 if (!AreGuidsEqual(m_decoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL))
4452 {
4453 m_pUserDecoderPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_DECODE, *m_pmfxSession.get(), m_decoderPluginParams.pluginGuid, 1));
4454 if (m_pUserDecoderPlugin.get() == NULL) sts = MFX_ERR_UNSUPPORTED;
4455 }
4456 }
4457 MSDK_CHECK_STATUS(sts, "LoadPlugin failed");
4458 }
4459
4460 // Load external encoder plugin
4461 if (isEncoderPlugin)
4462 {
4463 if (m_encoderPluginParams.type == MFX_PLUGINLOAD_TYPE_FILE && msdk_strnlen(m_encoderPluginParams.strPluginPath, sizeof(m_encoderPluginParams.strPluginPath)))
4464 {
4465 m_pUserEncoderModule.reset(new MFXVideoUSER(*m_pmfxSession.get()));
4466 m_pUserEncoderPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_ENCODE, *m_pmfxSession.get(), m_encoderPluginParams.pluginGuid, 1, m_encoderPluginParams.strPluginPath, (mfxU32)msdk_strnlen(m_encoderPluginParams.strPluginPath, sizeof(m_encoderPluginParams.strPluginPath))));
4467 if (m_pUserEncoderPlugin.get() == NULL) sts = MFX_ERR_UNSUPPORTED;
4468 }
4469 else
4470 {
4471 if (AreGuidsEqual(m_encoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL))
4472 {
4473 m_decoderPluginParams.pluginGuid = msdkGetPluginUID(m_initPar.Implementation, MSDK_VENCODE, m_mfxEncParams.mfx.CodecId);
4474 }
4475 if (!AreGuidsEqual(m_encoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL))
4476 {
4477 m_pUserEncoderPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_ENCODE, *m_pmfxSession.get(), m_encoderPluginParams.pluginGuid, 1));
4478 if (m_pUserEncoderPlugin.get() == NULL) sts = MFX_ERR_UNSUPPORTED;
4479 }
4480 }
4481 MSDK_CHECK_STATUS(sts, "LoadPlugin failed");
4482 }
4483
4484 // Load external pre-enc plugin
4485 if (isPreEncPlugin)
4486 {
4487 m_pUserEncPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_ENCODE, *m_pmfxSession.get(), MFX_PLUGINID_H264LA_HW, 1));
4488 if (m_pUserEncPlugin.get() == NULL) sts = MFX_ERR_UNSUPPORTED;
4489 MSDK_CHECK_STATUS(sts, "LoadPlugin failed");
4490 }
4491
4492 sts = SetAllocatorAndHandleIfRequired();
4493 MSDK_CHECK_STATUS(sts, "SetAllocatorAndHandleIfRequired failed");
4494
4495 if (isDec)
4496 m_pmfxDEC.reset(new MFXVideoDECODE((mfxSession)*m_pmfxSession));
4497 if (isVPP)
4498 m_pmfxVPP.reset(new MFXVideoMultiVPP((mfxSession)*m_pmfxSession));
4499 if (isPreEnc)
4500 m_pmfxPreENC.reset(new MFXVideoENC((mfxSession)*m_pmfxSession));
4501 if (isEnc)
4502 m_pmfxENC.reset(new MFXVideoENCODE((mfxSession)*m_pmfxSession));
4503
4504 if (isDec)
4505 {
4506 sts = m_pmfxDEC->Init(&m_mfxDecParams);
4507 MSDK_CHECK_STATUS(sts, "m_pmfxDEC->Init failed");
4508 }
4509
4510 if (isGenericPLugin)
4511 {
4512 sts = LoadGenericPlugin();
4513 MSDK_CHECK_STATUS(sts, "LoadGenericPlugin failed");
4514 }
4515
4516 if (isVPP)
4517 {
4518 if (m_bIsPlugin && m_bIsVpp)
4519 {
4520 mfxFrameAllocRequest request[2] = { };
4521 sts = m_pmfxVPP->QueryIOSurfMulti(&m_mfxPluginParams, request, &m_mfxVppParams);
4522 MSDK_CHECK_STATUS(sts, "m_pmfxVPP->QueryIOSurf failed");
4523
4524 sts = m_pmfxVPP->InitMulti(&m_mfxPluginParams, &m_mfxVppParams);
4525 }
4526 else if (m_bIsPlugin)
4527 sts = m_pmfxVPP->Init(&m_mfxPluginParams);
4528 else
4529 sts = m_pmfxVPP->Init(&m_mfxVppParams);
4530 MSDK_CHECK_STATUS(sts, "m_pmfxVPP->Init failed");
4531 }
4532
4533 if (isPreEnc)
4534 {
4535 sts = m_pmfxPreENC->Init(&m_mfxPreEncParams);
4536 MSDK_CHECK_STATUS(sts, "m_pmfxPreENC->Init failed");
4537 }
4538
4539 if (isEnc)
4540 {
4541 sts = m_pmfxENC->Init(&m_mfxEncParams);
4542 MSDK_CHECK_STATUS(sts, "m_pmfxENC->Init failed");
4543 }
4544
4545 // Joining sessions if required
4546 if (m_bIsJoinSession && m_pParentPipeline)
4547 {
4548 sts = m_pParentPipeline->Join(m_pmfxSession.get());
4549 MSDK_CHECK_STATUS(sts, "m_pParentPipeline->Join failed");
4550 m_bIsJoinSession = true;
4551 }
4552 return sts;
4553 }
4554
AllocAndInitVppDoNotUse(sInputParams * pInParams)4555 mfxStatus CTranscodingPipeline::AllocAndInitVppDoNotUse(sInputParams *pInParams)
4556 {
4557 std::vector<mfxU32> filtersDisabled;
4558 if (pInParams->DenoiseLevel == -1)
4559 {
4560 filtersDisabled.push_back(MFX_EXTBUFF_VPP_DENOISE); // turn off denoising (on by default)
4561 }
4562 filtersDisabled.push_back(MFX_EXTBUFF_VPP_SCENE_ANALYSIS); // turn off scene analysis (on by default)
4563
4564 if (filtersDisabled.size())
4565 {
4566 auto doNotUse = m_mfxVppParams.AddExtBuffer<mfxExtVPPDoNotUse>();
4567 delete[] doNotUse->AlgList;
4568
4569 doNotUse->NumAlg = (mfxU32)filtersDisabled.size();
4570 doNotUse->AlgList = new mfxU32 [doNotUse->NumAlg];
4571 MSDK_MEMCPY(doNotUse->AlgList, filtersDisabled.data(), sizeof(mfxU32)*filtersDisabled.size());
4572 }
4573
4574 return MFX_ERR_NONE;
4575 } // CTranscodingPipeline::AllocAndInitVppDoNotUse()
4576
FreeVppDoNotUse()4577 void CTranscodingPipeline::FreeVppDoNotUse()
4578 {
4579 mfxExtVPPDoNotUse* doNotUse = m_mfxVppParams;
4580 if (doNotUse)
4581 MSDK_SAFE_DELETE_ARRAY(doNotUse->AlgList);
4582 }
4583
AllocateSufficientBuffer(mfxBitstreamWrapper * pBS)4584 mfxStatus CTranscodingPipeline::AllocateSufficientBuffer(mfxBitstreamWrapper* pBS)
4585 {
4586 MSDK_CHECK_POINTER(pBS, MFX_ERR_NULL_PTR);
4587
4588 mfxVideoParam par;
4589 MSDK_ZERO_MEMORY(par);
4590
4591 // find out the required buffer size
4592 mfxStatus sts = m_pmfxENC->GetVideoParam(&par);
4593 MSDK_CHECK_STATUS(sts, "m_pmfxENC->GetVideoParam failed");
4594
4595 mfxU32 new_size = 0;
4596 if (par.mfx.CodecId == MFX_CODEC_JPEG)
4597 {
4598 new_size = 4 + (par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height * 3 + 1023);
4599 }
4600 else
4601 {
4602 new_size = par.mfx.BufferSizeInKB * par.mfx.BRCParamMultiplier * 1000u;
4603 }
4604
4605 pBS->Extend(new_size);
4606
4607 return MFX_ERR_NONE;
4608 } // CTranscodingPipeline::AllocateSufficientBuffer(mfxBitstreamWrapper* pBS)
4609
Join(MFXVideoSession * pChildSession)4610 mfxStatus CTranscodingPipeline::Join(MFXVideoSession *pChildSession)
4611 {
4612 mfxStatus sts = MFX_ERR_NONE;
4613 MSDK_CHECK_POINTER(pChildSession, MFX_ERR_NULL_PTR);
4614 sts = m_pmfxSession->JoinSession(*pChildSession);
4615 m_bIsJoinSession = (MFX_ERR_NONE == sts);
4616 return sts;
4617 } // CTranscodingPipeline::Join(MFXVideoSession *pChildSession)
4618
Run()4619 mfxStatus CTranscodingPipeline::Run()
4620 {
4621 mfxStatus sts = MFX_ERR_NONE;
4622
4623 msdk_stringstream ss;
4624 if (m_bDecodeEnable && m_bEncodeEnable)
4625 {
4626 sts = Transcode();
4627 ss << MSDK_STRING("CTranscodingPipeline::Run::Transcode() [") << GetSessionText() << MSDK_STRING("] failed");
4628 MSDK_CHECK_STATUS(sts, ss.str());
4629 }
4630 else if (m_bDecodeEnable)
4631 {
4632 sts = Decode();
4633 ss << MSDK_STRING("CTranscodingPipeline::Run::Decode() [") << GetSessionText() << MSDK_STRING("] failed");
4634 MSDK_CHECK_STATUS(sts, ss.str());
4635 }
4636 else if (m_bEncodeEnable)
4637 {
4638 sts = Encode();
4639 ss << MSDK_STRING("CTranscodingPipeline::Run::Encode() [") << GetSessionText() << MSDK_STRING("] failed");
4640 MSDK_CHECK_STATUS(sts, ss.str());
4641 }
4642 else
4643 return MFX_ERR_UNSUPPORTED;
4644
4645 return sts;
4646 }
4647
IncreaseReference(mfxFrameData * ptr)4648 void IncreaseReference(mfxFrameData *ptr)
4649 {
4650 msdk_atomic_inc16((volatile mfxU16 *)(&ptr->Locked));
4651 }
4652
DecreaseReference(mfxFrameData * ptr)4653 void DecreaseReference(mfxFrameData *ptr)
4654 {
4655 msdk_atomic_dec16((volatile mfxU16 *)&ptr->Locked);
4656 }
4657
SafetySurfaceBuffer(SafetySurfaceBuffer * pNext)4658 SafetySurfaceBuffer::SafetySurfaceBuffer(SafetySurfaceBuffer *pNext)
4659 :m_pNext(pNext),
4660 m_IsBufferingAllowed(true)
4661 {
4662 mfxStatus sts=MFX_ERR_NONE;
4663 pRelEvent = new MSDKEvent(sts,false,false);
4664 MSDK_CHECK_POINTER_NO_RET(pRelEvent);
4665
4666 pInsEvent = new MSDKEvent(sts,false,false);
4667 MSDK_CHECK_POINTER_NO_RET(pInsEvent);
4668
4669 } // SafetySurfaceBuffer::SafetySurfaceBuffer
4670
~SafetySurfaceBuffer()4671 SafetySurfaceBuffer::~SafetySurfaceBuffer()
4672 {
4673 delete pRelEvent;
4674 delete pInsEvent;
4675 } //SafetySurfaceBuffer::~SafetySurfaceBuffer()
4676
GetLength()4677 mfxU32 SafetySurfaceBuffer::GetLength()
4678 {
4679 std::lock_guard<std::mutex> guard(m_mutex);
4680 return (mfxU32)m_SList.size();
4681 }
4682
WaitForSurfaceRelease(mfxU32 msec)4683 mfxStatus SafetySurfaceBuffer::WaitForSurfaceRelease(mfxU32 msec)
4684 {
4685 return pRelEvent->TimedWait(msec);
4686 }
4687
WaitForSurfaceInsertion(mfxU32 msec)4688 mfxStatus SafetySurfaceBuffer::WaitForSurfaceInsertion(mfxU32 msec)
4689 {
4690 return pInsEvent->TimedWait(msec);
4691 }
4692
AddSurface(ExtendedSurface Surf)4693 void SafetySurfaceBuffer::AddSurface(ExtendedSurface Surf)
4694 {
4695 bool isBufferingAllowed = false;
4696
4697 {
4698 std::lock_guard<std::mutex> guard(m_mutex);
4699
4700 isBufferingAllowed = m_IsBufferingAllowed;
4701 if (isBufferingAllowed)
4702 {
4703 SurfaceDescriptor sDescriptor;
4704 // Locked is used to signal when we can free surface
4705 sDescriptor.Locked = 1;
4706 sDescriptor.ExtSurface = Surf;
4707
4708 if (Surf.pSurface)
4709 {
4710 IncreaseReference(&Surf.pSurface->Data);
4711 }
4712
4713 m_SList.push_back(sDescriptor);
4714 }
4715 }
4716
4717 if (isBufferingAllowed)
4718 {
4719 pInsEvent->Signal();
4720 }
4721
4722 } // SafetySurfaceBuffer::AddSurface(mfxFrameSurface1 *pSurf)
4723
GetSurface(ExtendedSurface & Surf)4724 mfxStatus SafetySurfaceBuffer::GetSurface(ExtendedSurface &Surf)
4725 {
4726 std::lock_guard<std::mutex> guard(m_mutex);
4727
4728 // no ready surfaces
4729 if (0 == m_SList.size())
4730 {
4731 MSDK_ZERO_MEMORY(Surf)
4732 return MFX_ERR_MORE_SURFACE;
4733 }
4734
4735 SurfaceDescriptor sDescriptor = m_SList.front();
4736
4737 Surf = sDescriptor.ExtSurface;
4738
4739
4740 return MFX_ERR_NONE;
4741
4742 } // SafetySurfaceBuffer::GetSurface()
4743
ReleaseSurface(mfxFrameSurface1 * pSurf)4744 mfxStatus SafetySurfaceBuffer::ReleaseSurface(mfxFrameSurface1* pSurf)
4745 {
4746 std::unique_lock<std::mutex> lock(m_mutex);
4747
4748 std::list<SurfaceDescriptor>::iterator it;
4749 for (it = m_SList.begin(); it != m_SList.end(); it++)
4750 {
4751 if (pSurf == it->ExtSurface.pSurface)
4752 {
4753 it->Locked--;
4754 if (it->ExtSurface.pSurface)
4755 DecreaseReference(&it->ExtSurface.pSurface->Data);
4756 if (0 == it->Locked)
4757 {
4758 m_SList.erase(it);
4759 lock.unlock();
4760
4761 // event operation should be out of synced context
4762 pRelEvent->Signal();
4763 }
4764
4765 return MFX_ERR_NONE;
4766 }
4767 }
4768
4769 return MFX_ERR_UNKNOWN;
4770 } // mfxStatus SafetySurfaceBuffer::ReleaseSurface(mfxFrameSurface1* pSurf)
4771
ReleaseSurfaceAll()4772 mfxStatus SafetySurfaceBuffer::ReleaseSurfaceAll()
4773 {
4774 std::lock_guard<std::mutex> guard(m_mutex);
4775
4776 m_SList.clear();
4777 m_IsBufferingAllowed = true;
4778 return MFX_ERR_NONE;
4779
4780 } // mfxStatus SafetySurfaceBuffer::ReleaseSurface(mfxFrameSurface1* pSurf)
4781
CancelBuffering()4782 void SafetySurfaceBuffer::CancelBuffering()
4783 {
4784 std::lock_guard<std::mutex> guard(m_mutex);
4785 m_IsBufferingAllowed=false;
4786 }
4787
FileBitstreamProcessor()4788 FileBitstreamProcessor::FileBitstreamProcessor()
4789 {
4790 m_Bitstream.TimeStamp=(mfxU64)-1;
4791 }
4792
~FileBitstreamProcessor()4793 FileBitstreamProcessor::~FileBitstreamProcessor()
4794 {
4795 if (m_pFileReader.get())
4796 m_pFileReader->Close();
4797 if (m_pFileWriter.get())
4798 m_pFileWriter->Close();
4799 }
4800
SetReader(std::unique_ptr<CSmplYUVReader> & reader)4801 mfxStatus FileBitstreamProcessor::SetReader(std::unique_ptr<CSmplYUVReader>& reader)
4802 {
4803 m_pYUVFileReader = std::move(reader);
4804
4805 return MFX_ERR_NONE;
4806 }
4807
SetReader(std::unique_ptr<CSmplBitstreamReader> & reader)4808 mfxStatus FileBitstreamProcessor::SetReader(std::unique_ptr<CSmplBitstreamReader>& reader)
4809 {
4810 m_pFileReader = std::move(reader);
4811 m_Bitstream.Extend(1024 * 1024);
4812
4813 return MFX_ERR_NONE;
4814 }
4815
SetWriter(std::unique_ptr<CSmplBitstreamWriter> & writer)4816 mfxStatus FileBitstreamProcessor::SetWriter(std::unique_ptr<CSmplBitstreamWriter>& writer)
4817 {
4818 m_pFileWriter = std::move(writer);
4819
4820 return MFX_ERR_NONE;
4821 }
4822
GetInputBitstream(mfxBitstreamWrapper ** pBitstream)4823 mfxStatus FileBitstreamProcessor::GetInputBitstream(mfxBitstreamWrapper **pBitstream)
4824 {
4825 if (!m_pFileReader.get())
4826 {
4827 return MFX_ERR_UNSUPPORTED;
4828 }
4829 mfxStatus sts = m_pFileReader->ReadNextFrame(&m_Bitstream);
4830 if (MFX_ERR_NONE == sts)
4831 {
4832 *pBitstream = &m_Bitstream;
4833 return sts;
4834 }
4835 return sts;
4836
4837 }
4838
GetInputFrame(mfxFrameSurface1 * pSurface)4839 mfxStatus FileBitstreamProcessor::GetInputFrame(mfxFrameSurface1 * pSurface)
4840 {
4841 //MSDK_CHECK_POINTER(pSurface);
4842 if (!m_pYUVFileReader.get())
4843 {
4844 return MFX_ERR_UNSUPPORTED;
4845 }
4846 return m_pYUVFileReader->LoadNextFrame(pSurface);
4847 }
4848
ProcessOutputBitstream(mfxBitstreamWrapper * pBitstream)4849 mfxStatus FileBitstreamProcessor::ProcessOutputBitstream(mfxBitstreamWrapper* pBitstream)
4850 {
4851 if (m_pFileWriter.get())
4852 return m_pFileWriter->WriteNextFrame(pBitstream, false);
4853 else
4854 return MFX_ERR_NONE;
4855
4856 }
4857
ResetInput()4858 mfxStatus FileBitstreamProcessor::ResetInput()
4859 {
4860 if (m_pFileReader.get())
4861 {
4862 m_pFileReader->Reset();
4863
4864 // Reset input bitstream state
4865 m_Bitstream.DataFlag = 0;
4866 }
4867 if (m_pYUVFileReader.get())
4868 {
4869 m_pYUVFileReader->Reset();
4870 }
4871 return MFX_ERR_NONE;
4872 }
4873
ResetOutput()4874 mfxStatus FileBitstreamProcessor::ResetOutput()
4875 {
4876 if (m_pFileWriter.get())
4877 {
4878 m_pFileWriter->Reset();
4879 }
4880 return MFX_ERR_NONE;
4881 }
4882
IsNulOutput()4883 bool FileBitstreamProcessor::IsNulOutput()
4884 {
4885 return !m_pFileWriter.get();
4886 }
4887
ModifyParamsUsingPresets(sInputParams & params,mfxF64 fps,mfxU32 width,mfxU32 height)4888 void CTranscodingPipeline::ModifyParamsUsingPresets(sInputParams& params, mfxF64 fps, mfxU32 width, mfxU32 height)
4889 {
4890
4891 COutputPresetParameters presetParams = CPresetManager::Inst.GetPreset(params.PresetMode, params.EncodeId, fps, width, height, params.libType != MFX_IMPL_SOFTWARE);
4892
4893 if (params.shouldPrintPresets)
4894 {
4895 msdk_printf(MSDK_STRING("Preset-controlled parameters (%s):\n"), presetParams.PresetName.c_str());
4896 }
4897
4898 if (!params.nRateControlMethod)
4899 {
4900 MODIFY_AND_PRINT_PARAM_EXT(params.nExtBRC, ExtBRCUsage, (ExtBRCType)presetParams.ExtBRCUsage, params.shouldPrintPresets);
4901 }
4902 if (presetParams.RateControlMethod == MFX_RATECONTROL_LA_EXT)
4903 {
4904 // Use external LA
4905 params.bEnableExtLA = true;
4906 params.nRateControlMethod = 0;
4907 if(params.shouldPrintPresets)
4908 {
4909 msdk_printf(MSDK_STRING("RateControlMethod: ExtLA\n"));
4910 }
4911 }
4912 else
4913 {
4914 MODIFY_AND_PRINT_PARAM(params.nRateControlMethod, RateControlMethod, params.shouldPrintPresets);
4915 }
4916
4917 MODIFY_AND_PRINT_PARAM(params.nAdaptiveMaxFrameSize, AdaptiveMaxFrameSize, params.shouldPrintPresets);
4918 MODIFY_AND_PRINT_PARAM(params.nAsyncDepth, AsyncDepth, params.shouldPrintPresets);
4919 MODIFY_AND_PRINT_PARAM(params.nBRefType, BRefType, params.shouldPrintPresets);
4920 MODIFY_AND_PRINT_PARAM(params.bEnableBPyramid, EnableBPyramid, params.shouldPrintPresets);
4921 // MODIFY_AND_PRINT_PARAM(params., EnablePPyramid, params.shouldPrintPresets);
4922 MODIFY_AND_PRINT_PARAM(params.GopRefDist, GopRefDist, params.shouldPrintPresets);
4923 MODIFY_AND_PRINT_PARAM(params.IntRefCycleDist, IntRefCycleDist, params.shouldPrintPresets);
4924 MODIFY_AND_PRINT_PARAM(params.IntRefCycleSize, IntRefCycleSize, params.shouldPrintPresets);
4925 MODIFY_AND_PRINT_PARAM(params.IntRefQPDelta, IntRefQPDelta, params.shouldPrintPresets);
4926 MODIFY_AND_PRINT_PARAM(params.IntRefType, IntRefType, params.shouldPrintPresets);
4927 MODIFY_AND_PRINT_PARAM(params.LowDelayBRC, LowDelayBRC, params.shouldPrintPresets);
4928 MODIFY_AND_PRINT_PARAM(params.nTargetUsage, TargetUsage, params.shouldPrintPresets);
4929 MODIFY_AND_PRINT_PARAM(params.WeightedBiPred, WeightedBiPred, params.shouldPrintPresets);
4930 MODIFY_AND_PRINT_PARAM(params.WeightedPred, WeightedPred, params.shouldPrintPresets);
4931
4932 MODIFY_AND_PRINT_PARAM(params.GopPicSize, GopPicSize, params.shouldPrintPresets);
4933
4934 if (params.nRateControlMethod != MFX_RATECONTROL_CQP)
4935 {
4936 MODIFY_AND_PRINT_PARAM(params.MaxKbps, MaxKbps, params.shouldPrintPresets);
4937 MODIFY_AND_PRINT_PARAM(params.nBitRate, TargetKbps, params.shouldPrintPresets);
4938 presetParams.BufferSizeInKB = (mfxU16)params.nBitRate; // Update bitrate to reflect manually set bitrate. BufferSize should be enough for 1 second of video
4939 MODIFY_AND_PRINT_PARAM(params.BufferSizeInKB, BufferSizeInKB, params.shouldPrintPresets);
4940 }
4941
4942 MODIFY_AND_PRINT_PARAM(params.nMaxFrameSize, MaxFrameSize, params.shouldPrintPresets);
4943 MODIFY_AND_PRINT_PARAM(params.nLADepth, LookAheadDepth, params.shouldPrintPresets);
4944 if (params.shouldPrintPresets)
4945 {
4946 msdk_printf(MSDK_STRING("\n"));
4947 }
4948
4949 }
4950