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