History

Initial Commit

Ethan Hugg committed 12 years ago

Commit 70e5e621 parent bd509b2308 files · +97095 −-5Browse files

Showing the changes to codec/encoder/core/src/wels_preprocess.cpp (1 of 308 files). Show all

Unified · Split

codec/encoder/core/src/wels_preprocess.cpp+1126−0
@@ -0,0 +1,1126 @@
1+/*!
2+ * \copy
3+ * Copyright (c) 2013, Cisco Systems
4+ * All rights reserved.
5+ *
6+ * Redistribution and use in source and binary forms, with or without
7+ * modification, are permitted provided that the following conditions
8+ * are met:
9+ *
10+ * * Redistributions of source code must retain the above copyright
11+ * notice, this list of conditions and the following disclaimer.
12+ *
13+ * * Redistributions in binary form must reproduce the above copyright
14+ * notice, this list of conditions and the following disclaimer in
15+ * the documentation and/or other materials provided with the
16+ * distribution.
17+ *
18+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29+ * POSSIBILITY OF SUCH DAMAGE.
30+ *
31+ */
32+
33+#if defined(WIN32)
34+#include <windows.h>
35+#elif defined(MACOS)
36+#include "bundleloader.h"
37+#elif defined(__GNUC__)
38+#include <dlfcn.h>
39+#endif
40+
41+#include <stdio.h>
42+#include <stdlib.h>
43+#include <string.h>
44+#include <assert.h>
45+#include "wels_preprocess.h"
46+#include "memory_align.h"
47+#include "encoder.h"
48+#include "extern.h"
49+#include "picture_handle.h"
50+#include "encoder_context.h"
51+#include "utils.h"
52+
53+
54+namespace WelsSVCEnc {
55+
56+#define WelsSafeDelete(p) if(p){ delete (p); (p) = NULL; }
57+
58+//***** entry API declaration ************************************************************************//
59+typedef EResult (WELSAPI *pfnCreateVpInterface) (void **, int );
60+typedef EResult (WELSAPI *pfnDestroyVpInterface) (void * , int );
61+
62+int32_t WelsInitScaledPic( SWelsSvcCodingParam *pParam, Scaled_Picture *pScaledPic, CMemoryAlign *pMemoryAlign );
63+bool_t JudgeNeedOfScaling( SWelsSvcCodingParam *pParam, Scaled_Picture * pScaledPic );
64+void FreeScaledPic( Scaled_Picture *pScaledPic, CMemoryAlign *pMemoryAlign );
65+
66+//******* table definition ***********************************************************************//
67+const uint8_t g_kuiRefTemporalIdx[MAX_TEMPORAL_LEVEL][MAX_GOP_SIZE] =
68+{
69+ { 0, }, // 0
70+ { 0, 0, }, // 1
71+ { 0, 0, 0, 1, }, // 2
72+ { 0, 0, 0, 2, 0, 1, 1, 2, }, // 3
73+ { 0, 0, 0, 3, 0, 2, 2, 3, 0, 1, 1, 3, 1, 2, 2, 3 } // 4
74+};
75+
76+const int32_t g_kiPixMapSizeInBits = sizeof(uint8_t) * 8;
77+
78+
79+inline void WelsUpdateSpatialIdxMap(sWelsEncCtx * pEncCtx, int32_t iPos, SPicture * pPic, int32_t iDidx)
80+{
81+ pEncCtx->sSpatialIndexMap[iPos].pSrc = pPic;
82+ pEncCtx->sSpatialIndexMap[iPos].iDid = iDidx;
83+}
84+
85+
86+//***************************************************************************************************//
87+CWelsLib::CWelsLib(void *pEncCtx)
88+{
89+ m_pInterface[0] = m_pInterface[1] = NULL;
90+#if defined(WIN32)
91+ const str_t WelsVPLib[] = "welsvp.dll";
92+ HMODULE shModule = LoadLibrary(WelsVPLib);
93+ if(!shModule)
94+ WelsLog( pEncCtx, WELS_LOG_ERROR, "welsvp load lib dynamic failed module=%x\n", shModule );
95+
96+#elif defined(MACOS)
97+ const str_t WelsVPLib[] = "welsvp.bundle";
98+ str_t pCurPath[256];
99+ GetCurrentModulePath(pCurPath, 256);
100+ strlcat(pCurPath, WelsVPLib, 256);
101+ CFBundleRef shModule = LoadBundle(pCurPath);
102+ if(!shModule)
103+ WelsLog( pEncCtx, WELS_LOG_ERROR, "welsvp load lib dynamic failed module=%x\n", shModule );
104+
105+#elif defined(__GNUC__)
106+ const str_t WelsVPLib[] = "./libwelsvp.so";
107+ void* shModule = NULL;
108+ shModule = dlopen(WelsVPLib, RTLD_LAZY);
109+ if (shModule == NULL)
110+ printf("dlopen %s iRet=%x, err=%s\n", WelsVPLib, shModule, dlerror());
111+#endif
112+
113+ m_pVpLib = (void *)shModule;
114+}
115+
116+CWelsLib::~CWelsLib()
117+{
118+ if (m_pVpLib)
119+ {
120+#if defined(WIN32)
121+ HMODULE shModule = (HMODULE)m_pVpLib;
122+ FreeLibrary(shModule);
123+
124+#elif defined(MACOS)
125+ CFBundleRef shModule = (CFBundleRef)m_pVpLib;
126+ FreeBundle(shModule);
127+
128+#elif defined(__GNUC__)
129+ void* shModule = m_pVpLib;
130+ dlclose(shModule);
131+#endif
132+ m_pVpLib = NULL;
133+ }
134+}
135+
136+void* CWelsLib::QueryFunction(const str_t *pName)
137+{
138+ void *pFunc = NULL;
139+ if (m_pVpLib)
140+ {
141+#if defined(WIN32)
142+ HMODULE shModule = (HMODULE)m_pVpLib;
143+ pFunc = (void *)GetProcAddress(shModule, pName);
144+
145+#elif defined(MACOS)
146+ CFBundleRef shModule = (CFBundleRef)m_pVpLib;
147+ pFunc = (void *)GetProcessAddress(shModule, pName);
148+
149+#elif defined(__GNUC__)
150+ void* shModule = m_pVpLib;
151+ pFunc = (void *)dlsym(shModule, pName);
152+ if (pFunc == NULL)
153+ printf("dlsym %s iRet=%p, err=%s\n", shModule, pFunc, dlerror());
154+#endif
155+ }
156+ return pFunc;
157+}
158+
159+int32_t CWelsLib::CreateIface(void **ppEncCtx)
160+{
161+ if (m_pVpLib)
162+ {
163+ pfnCreateVpInterface pCreateVpInterface = NULL;
164+ pfnDestroyVpInterface pDestroyVpInterface = NULL;
165+
166+ pCreateVpInterface = (pfnCreateVpInterface) QueryFunction("CreateVpInterface");
167+ pDestroyVpInterface = (pfnDestroyVpInterface) QueryFunction("DestroyVpInterface");
168+
169+ m_pInterface[0] = (void *)pCreateVpInterface;
170+ m_pInterface[1] = (void *)pDestroyVpInterface;
171+
172+ if (m_pInterface[0] && m_pInterface[1])
173+ pCreateVpInterface(ppEncCtx, WELSVP_INTERFACE_VERION);
174+ }
175+ else
176+ {
177+ }
178+
179+ return ppEncCtx ? 0 : 1;
180+}
181+
182+int32_t CWelsLib::DestroyIface(void *pEncCtx)
183+{
184+ if (pEncCtx)
185+ {
186+ pfnDestroyVpInterface pDestroyVpInterface = (pfnDestroyVpInterface) m_pInterface[1];
187+ if (pDestroyVpInterface)
188+ {
189+ pDestroyVpInterface(pEncCtx, WELSVP_INTERFACE_VERION);
190+ }
191+ else
192+ {
193+ }
194+ }
195+
196+ return 0;
197+}
198+
199+/***************************************************************************
200+*
201+* implement of the interface
202+*
203+***************************************************************************/
204+
205+CWelsPreProcess::CWelsPreProcess(void *pEncCtx)
206+{
207+ m_pInterfaceVp = NULL;
208+ m_pEncLib = NULL;
209+ m_bInitDone = false;
210+ m_bOfficialBranch = FALSE;
211+ m_pEncCtx = pEncCtx;
212+ memset(&m_sScaledPicture, 0, sizeof(m_sScaledPicture));
213+}
214+
215+CWelsPreProcess::~CWelsPreProcess()
216+{
217+ FreeScaledPic(&m_sScaledPicture, static_cast<sWelsEncCtx *>(m_pEncCtx)->pMemAlign);
218+ WelsPreprocessDestroy();
219+}
220+
221+int32_t CWelsPreProcess::WelsPreprocessCreate()
222+{
223+ if (m_pEncLib == NULL && m_pInterfaceVp == NULL)
224+ {
225+ m_pEncLib = new CWelsLib(m_pEncCtx);
226+ if (!m_pEncLib)
227+ goto exit;
228+
229+ m_pEncLib->CreateIface((void **)&m_pInterfaceVp);
230+ if (!m_pInterfaceVp)
231+ goto exit;
232+ }
233+ else
234+ goto exit;
235+
236+ return 0;
237+
238+exit:
239+ WelsPreprocessDestroy();
240+ return 1;
241+}
242+
243+int32_t CWelsPreProcess::WelsPreprocessDestroy()
244+{
245+ if (m_pEncLib)
246+ {
247+ m_pEncLib->DestroyIface((void *)m_pInterfaceVp);
248+ m_pInterfaceVp = NULL;
249+ WelsSafeDelete(m_pEncLib);
250+ }
251+
252+ return 0;
253+}
254+
255+int32_t CWelsPreProcess::WelsPreprocessReset ( void *pCtx )
256+{
257+ sWelsEncCtx *pEncCtx = (sWelsEncCtx *)pCtx;
258+ int32_t iRet = -1;
259+
260+ if (pEncCtx)
261+ {
262+ FreeScaledPic(&m_sScaledPicture, pEncCtx->pMemAlign);
263+ iRet = InitLastSpatialPictures(pEncCtx);
264+ iRet = WelsInitScaledPic(pEncCtx->pSvcParam, &m_sScaledPicture, pEncCtx->pMemAlign);
265+ }
266+
267+ return iRet;
268+}
269+
270+int32_t CWelsPreProcess::WelsPreprocessStep1( void *pCtx, const SSourcePicture **kppSrcPicList, const int32_t kiConfiguredLayerNum )
271+{
272+ sWelsEncCtx *pEncCtx = (sWelsEncCtx *)pCtx;
273+ SWelsSvcCodingParam *pSvcParam = pEncCtx->pSvcParam;
274+ int32_t iNumDependencyLayer = (int32_t)pSvcParam->iNumDependencyLayer;
275+ int32_t iSpatialNum = 0;
276+
277+ if (!m_bInitDone)
278+ {
279+ if (WelsPreprocessCreate() != 0)
280+ return -1;
281+ if (WelsPreprocessReset(pEncCtx) != 0)
282+ return -1;
283+
284+ m_bOfficialBranch = (iNumDependencyLayer != kiConfiguredLayerNum);
285+ if ( !m_bOfficialBranch && (iNumDependencyLayer == 1) )
286+ {
287+ // check the input source uiSize to decide if need switch to official branch
288+ // NOTICE: the layernum=1 case is confused in official/non-official cases!
289+ SSourcePicture **pic_queue = (SSourcePicture **)kppSrcPicList;
290+ for (int32_t i=0; i<iNumDependencyLayer; i++)
291+ {
292+ if ( pSvcParam->sDependencyLayers[i].iFrameWidth != pic_queue[i]->iPicWidth ||
293+ pSvcParam->sDependencyLayers[i].iFrameHeight != pic_queue[i]->iPicHeight )
294+ {
295+ m_bOfficialBranch = TRUE;
296+ break;
297+ }
298+ }
299+ }
300+ m_bInitDone = TRUE;
301+ }
302+
303+ if (m_pInterfaceVp == NULL)
304+ return -1;
305+
306+ if ( kiConfiguredLayerNum <= 0 )
307+ return -1;
308+
309+ pEncCtx->pVaa->bSceneChangeFlag = pEncCtx->pVaa->bIdrPeriodFlag = false;
310+ if( pSvcParam->uiIntraPeriod )
311+ pEncCtx->pVaa->bIdrPeriodFlag = ( 1 + pEncCtx->iFrameIndex >= (int32_t)pSvcParam->uiIntraPeriod ) ? true : false;
312+
313+ if ( m_bOfficialBranch ) // Perform Down Sampling potentially due to application
314+ {
315+ assert( kiConfiguredLayerNum == 1 );
316+ iSpatialNum = SingleLayerPreprocess( pEncCtx, kppSrcPicList[0], &m_sScaledPicture );
317+ }
318+ else // for console each spatial pictures are available there
319+ {
320+ iSpatialNum = kiConfiguredLayerNum;
321+ MultiLayerPreprocess( pEncCtx, kppSrcPicList, iSpatialNum );
322+ }
323+
324+ return iSpatialNum;
325+}
326+
327+int32_t CWelsPreProcess::WelsPreprocessStep3( void *pCtx, const int32_t kiDidx )
328+{
329+ sWelsEncCtx *pEncCtx = (sWelsEncCtx *)pCtx;
330+ SWelsSvcCodingParam *pSvcParam = pEncCtx->pSvcParam;
331+ bool_t bNeededMbAq = (pSvcParam->bEnableAdaptiveQuant && (pEncCtx->eSliceType == P_SLICE));
332+ bool_t bCalculateBGD = (pEncCtx->eSliceType == P_SLICE && pSvcParam->bEnableBackgroundDetection);
333+
334+ int32_t iCurTemporalIdx = pEncCtx->uiSpatialLayersInTemporal[kiDidx] - 1;
335+
336+ int32_t iRefTemporalIdx = (int32_t)g_kuiRefTemporalIdx[pSvcParam->iDecompStages][pEncCtx->iCodingIndex & (pSvcParam->uiGopSize-1)];
337+ if ( pEncCtx->uiTemporalId == 0 && pEncCtx->pLtr[pEncCtx->uiDependencyId].bReceivedT0LostFlag )
338+ iRefTemporalIdx = pEncCtx->uiSpatialLayersInTemporal[kiDidx] + pEncCtx->pVaa->uiValidLongTermPicIdx;
339+
340+ SPicture *pCurPic = pEncCtx->pSpatialPic[kiDidx][iCurTemporalIdx];
341+ SPicture *pRefPic = pEncCtx->pSpatialPic[kiDidx][iRefTemporalIdx];
342+ {
343+ SPicture *pLastPic= m_pLastSpatialPicture[kiDidx][0];
344+ bool_t bCalculateSQDiff = ((pLastPic->pData[0] == pRefPic->pData[0]) && bNeededMbAq);
345+ bool_t bCalculateVar = (pSvcParam->iRCMode == RC_MODE1 && pEncCtx->eSliceType == I_SLICE);
346+
347+ VaaCalculation( pEncCtx->pVaa, pCurPic, pRefPic, bCalculateSQDiff, bCalculateVar, bCalculateBGD);
348+ }
349+
350+ if (pSvcParam->bEnableBackgroundDetection)
351+ {
352+ BackgroundDetection(pEncCtx->pVaa, pCurPic, pRefPic, bCalculateBGD && pRefPic->iPictureType != I_SLICE);
353+ }
354+
355+ if ( bNeededMbAq )
356+ {
357+ SPicture *pCurPic = m_pLastSpatialPicture[kiDidx][1];
358+ SPicture *pRefPic = m_pLastSpatialPicture[kiDidx][0];
359+
360+ AdaptiveQuantCalculation( pEncCtx->pVaa, pCurPic, pRefPic );
361+ }
362+
363+ if ( pSvcParam->bEnableRc )
364+ {
365+ AnalyzePictureComplexity( pEncCtx, pCurPic, pRefPic, kiDidx, bCalculateBGD );
366+ }
367+
368+ WelsExchangeSpatialPictures( &m_pLastSpatialPicture[kiDidx][1], &m_pLastSpatialPicture[kiDidx][0] );
369+
370+ return 0;
371+}
372+
373+
374+/*
375+* SingleLayerPreprocess: down sampling if applicable
376+* @return: exact number of spatial layers need to encoder indeed
377+*/
378+int32_t CWelsPreProcess::SingleLayerPreprocess( void *pCtx, const SSourcePicture *kpSrc, Scaled_Picture * pScaledPicture )
379+{
380+ sWelsEncCtx *pEncCtx = (sWelsEncCtx *)pCtx;
381+ SWelsSvcCodingParam *pSvcParam = pEncCtx->pSvcParam;
382+ int8_t iDependencyId = pSvcParam->iNumDependencyLayer - 1;
383+ int32_t iPicturePos = pEncCtx->uiSpatialLayersInTemporal[iDependencyId] - 1;
384+
385+ SPicture *pSrcPic = NULL; // large
386+ SPicture *pDstPic = NULL; // small
387+ SDLayerParam *pDlayerParam = NULL;
388+ int32_t iSpatialNum = 0;
389+ int32_t iSrcWidth = 0;
390+ int32_t iSrcHeight = 0;
391+ int32_t iTargetWidth = 0;
392+ int32_t iTargetHeight = 0;
393+ int32_t iTemporalId = 0;
394+ int32_t iActualSpatialLayerNum = 0;
395+
396+ pDlayerParam = &pSvcParam->sDependencyLayers[iDependencyId];
397+ iTargetWidth = pDlayerParam->iFrameWidth;
398+ iTargetHeight = pDlayerParam->iFrameHeight;
399+ iTemporalId = pDlayerParam->uiCodingIdx2TemporalId[pEncCtx->iCodingIndex & (pSvcParam->uiGopSize-1)];
400+ iSrcWidth = pSvcParam->SUsedPicRect.iWidth;
401+ iSrcHeight = pSvcParam->SUsedPicRect.iHeight;
402+
403+ pSrcPic = pScaledPicture->pScaledInputPicture ? pScaledPicture->pScaledInputPicture : pEncCtx->pSpatialPic[iDependencyId][iPicturePos];
404+
405+ WelsMoveMemoryWrapper( pSvcParam, pSrcPic, kpSrc, iSrcWidth, iSrcHeight );
406+
407+ if( pSvcParam->bEnableDenoise )
408+ BilateralDenoising(pSrcPic, iSrcWidth, iSrcHeight);
409+
410+ // different scaling in between input picture and dst highest spatial picture.
411+ int32_t iShrinkWidth = iSrcWidth;
412+ int32_t iShrinkHeight = iSrcHeight;
413+ pDstPic = pSrcPic;
414+ if ( pScaledPicture->pScaledInputPicture )
415+ {
416+ // for highest downsampling
417+ pDstPic = pEncCtx->pSpatialPic[iDependencyId][iPicturePos];
418+ iShrinkWidth = pScaledPicture->iScaledWidth[iDependencyId];
419+ iShrinkHeight = pScaledPicture->iScaledHeight[iDependencyId];
420+ }
421+ DownsamplePadding(pSrcPic, pDstPic, iSrcWidth, iSrcHeight, iShrinkWidth, iShrinkHeight, iTargetWidth, iTargetHeight);
422+
423+ if(pSvcParam->bEnableSceneChangeDetect && !pEncCtx->pVaa->bIdrPeriodFlag && !(pEncCtx->iCodingIndex & (pSvcParam->uiGopSize-1))){
424+ SPicture *pRefPic = pEncCtx->pLtr[iDependencyId].bReceivedT0LostFlag ?
425+ pEncCtx->pSpatialPic[iDependencyId][pEncCtx->uiSpatialLayersInTemporal[iDependencyId] + pEncCtx->pVaa->uiValidLongTermPicIdx] : m_pLastSpatialPicture[iDependencyId][0];
426+
427+ pEncCtx->pVaa->bSceneChangeFlag = DetectSceneChange(pDstPic, pRefPic);
428+ }
429+
430+ for( int32_t i=0;i<pSvcParam->iNumDependencyLayer;i++ ){
431+ if( pSvcParam->sDependencyLayers[i].uiCodingIdx2TemporalId[pEncCtx->iCodingIndex & (pSvcParam->uiGopSize-1)]
432+ != INVALID_TEMPORAL_ID ){
433+ ++ iActualSpatialLayerNum;
434+ }
435+ }
436+
437+ if ( iTemporalId != INVALID_TEMPORAL_ID )
438+ {
439+ WelsUpdateSpatialIdxMap(pEncCtx, iActualSpatialLayerNum - 1, pDstPic, iDependencyId);
440+ ++ iSpatialNum;
441+ -- iActualSpatialLayerNum;
442+ }
443+
444+ m_pLastSpatialPicture[iDependencyId][1] = pEncCtx->pSpatialPic[iDependencyId][iPicturePos];
445+ -- iDependencyId;
446+
447+ // generate other spacial layer
448+ // pSrc is
449+ // -- padded input pic, if downsample should be applied to generate highest layer, [if] block above
450+ // -- highest layer, if no downsampling, [else] block above
451+ if ( pSvcParam->iNumDependencyLayer > 1 )
452+ {
453+ while (iDependencyId >= 0)
454+ {
455+ pDlayerParam = &pSvcParam->sDependencyLayers[iDependencyId];
456+ iTargetWidth = pDlayerParam->iFrameWidth;
457+ iTargetHeight = pDlayerParam->iFrameHeight;
458+ iTemporalId = pDlayerParam->uiCodingIdx2TemporalId[pEncCtx->iCodingIndex & (pSvcParam->uiGopSize-1)];
459+ iPicturePos = pEncCtx->uiSpatialLayersInTemporal[iDependencyId] - 1;
460+
461+ // NOT work for CGS, FIXME
462+ // spatial layer is able to encode indeed
463+ if ( (iTemporalId != INVALID_TEMPORAL_ID) )
464+ {
465+ // down sampling performed
466+ if( NULL == pSrcPic )
467+ return -1;
468+
469+ pDstPic = pEncCtx->pSpatialPic[iDependencyId][iPicturePos]; // small
470+ iShrinkWidth = pScaledPicture->iScaledWidth[iDependencyId];
471+ iShrinkHeight = pScaledPicture->iScaledHeight[iDependencyId];
472+ DownsamplePadding(pSrcPic, pDstPic, iSrcWidth, iSrcHeight, iShrinkWidth, iShrinkHeight, iTargetWidth, iTargetHeight);
473+
474+ WelsUpdateSpatialIdxMap(pEncCtx, iActualSpatialLayerNum - 1, pDstPic, iDependencyId);
475+
476+ -- iActualSpatialLayerNum;
477+ ++ iSpatialNum;
478+
479+ m_pLastSpatialPicture[iDependencyId][1] = pEncCtx->pSpatialPic[iDependencyId][iPicturePos];
480+ }
481+ -- iDependencyId;
482+ }
483+ }
484+
485+ return iSpatialNum;
486+}
487+
488+int32_t CWelsPreProcess::MultiLayerPreprocess( void *pCtx, const SSourcePicture **kppSrcPicList, const int32_t kiSpatialNum )
489+{
490+ sWelsEncCtx *pEncCtx = (sWelsEncCtx *)pCtx;
491+ SWelsSvcCodingParam *pSvcParam = pEncCtx->pSvcParam;
492+ const SSourcePicture *pSrc = NULL;
493+ SPicture *pDstPic = NULL;
494+ const int32_t iSpatialLayersCfgCount = pSvcParam->iNumDependencyLayer; // count number of spatial layers to be encoded in cfg
495+ int32_t i = 0;
496+ int32_t j = -1;
497+
498+ do {
499+ pSrc = kppSrcPicList[i];
500+
501+ // do not clear j, just let it continue to save complexity
502+ do {
503+ ++ j;
504+ if ( pSvcParam->sDependencyLayers[j].iFrameWidth == pSrc->iPicWidth &&
505+ pSvcParam->sDependencyLayers[j].iFrameHeight== pSrc->iPicHeight )
506+ {
507+ break;
508+ }
509+ } while( j < iSpatialLayersCfgCount );
510+
511+ assert( j < iSpatialLayersCfgCount );
512+ pDstPic = pEncCtx->pSpatialPic[j][pEncCtx->uiSpatialLayersInTemporal[j]-1];
513+
514+ WelsUpdateSpatialIdxMap(pEncCtx, i, pDstPic, j);
515+
516+ WelsMoveMemoryWrapper( pSvcParam, pDstPic, pSrc, pSrc->iPicWidth, pSrc->iPicHeight );
517+
518+ if(pSvcParam->bEnableDenoise)
519+ BilateralDenoising(pDstPic, pSrc->iPicWidth, pSrc->iPicHeight);
520+
521+ m_pLastSpatialPicture[j][1] = pDstPic;
522+ ++ i;
523+ } while( i < kiSpatialNum );
524+
525+ if( pSvcParam->bEnableSceneChangeDetect && (kiSpatialNum == pSvcParam->iNumDependencyLayer) && !pEncCtx->pVaa->bIdrPeriodFlag )
526+ {
527+ SPicture *pRef = pEncCtx->pLtr[0].bReceivedT0LostFlag ?
528+ pEncCtx->pSpatialPic[0][pEncCtx->uiSpatialLayersInTemporal[0] + pEncCtx->pVaa->uiValidLongTermPicIdx] : m_pLastSpatialPicture[0][0];
529+
530+ pEncCtx->pVaa->bSceneChangeFlag = DetectSceneChange(pDstPic, pRef);
531+ }
532+
533+ return 0;
534+}
535+
536+/*!
537+ * \brief Whether input picture need be scaled?
538+ */
539+bool_t JudgeNeedOfScaling( SWelsSvcCodingParam *pParam, Scaled_Picture * pScaledPicture )
540+{
541+ const int32_t kiInputPicWidth = pParam->SUsedPicRect.iWidth;
542+ const int32_t kiInputPicHeight = pParam->SUsedPicRect.iHeight;
543+ const int32_t kiDstPicWidth = pParam->sDependencyLayers[pParam->iNumDependencyLayer-1].iActualWidth;
544+ const int32_t kiDstPicHeight = pParam->sDependencyLayers[pParam->iNumDependencyLayer-1].iActualHeight;
545+ bool_t bNeedDownsampling = true;
546+
547+ int32_t iSpatialIdx = pParam->iNumDependencyLayer-1;
548+
549+ if ( kiDstPicWidth >= kiInputPicWidth && kiDstPicHeight >= kiInputPicHeight )
550+ {
551+ iSpatialIdx --; // highest D layer do not need downsampling
552+ bNeedDownsampling = false;
553+ }
554+
555+ for(; iSpatialIdx >= 0; iSpatialIdx --)
556+ {
557+ SDLayerParam *pCurLayer = &pParam->sDependencyLayers[iSpatialIdx];
558+ int32_t iCurDstWidth = pCurLayer->iActualWidth;
559+ int32_t iCurDstHeight = pCurLayer->iActualHeight;
560+ int32_t iInputWidthXDstHeight = kiInputPicWidth * iCurDstHeight;
561+ int32_t iInputHeightXDstWidth = kiInputPicHeight * iCurDstWidth;
562+
563+ if (iInputWidthXDstHeight > iInputHeightXDstWidth)
564+ {
565+ pScaledPicture->iScaledWidth[iSpatialIdx] = iCurDstWidth;
566+ pScaledPicture->iScaledHeight[iSpatialIdx] = iInputHeightXDstWidth / kiInputPicWidth;
567+ }else {
568+ pScaledPicture->iScaledWidth[iSpatialIdx] = iInputWidthXDstHeight / kiInputPicHeight;
569+ pScaledPicture->iScaledHeight[iSpatialIdx] = iCurDstHeight;
570+ }
571+ }
572+
573+ return bNeedDownsampling;
574+}
575+
576+int32_t WelsInitScaledPic( SWelsSvcCodingParam *pParam, Scaled_Picture *pScaledPicture, CMemoryAlign *pMemoryAlign )
577+{
578+ bool_t bInputPicNeedScaling = JudgeNeedOfScaling( pParam, pScaledPicture );
579+ if( bInputPicNeedScaling )
580+ {
581+ pScaledPicture->pScaledInputPicture = AllocPicture(pMemoryAlign, pParam->SUsedPicRect.iWidth, pParam->SUsedPicRect.iHeight, false);
582+ if( pScaledPicture->pScaledInputPicture == NULL )
583+ return -1;
584+ }
585+ return 0;
586+}
587+
588+void FreeScaledPic(Scaled_Picture *pScaledPicture, CMemoryAlign *pMemoryAlign)
589+{
590+ if ( pScaledPicture->pScaledInputPicture )
591+ {
592+ FreePicture( pMemoryAlign, &pScaledPicture->pScaledInputPicture );
593+ pScaledPicture->pScaledInputPicture = NULL;
594+ }
595+}
596+
597+int32_t CWelsPreProcess::InitLastSpatialPictures( void *pCtx )
598+{
599+ sWelsEncCtx *pEncCtx = (sWelsEncCtx *)pCtx;
600+ SWelsSvcCodingParam *pParam = pEncCtx->pSvcParam;
601+ const int32_t kiDlayerCount = pParam->iNumDependencyLayer;
602+ int32_t iDlayerIndex = 0;
603+
604+ for (; iDlayerIndex<kiDlayerCount; iDlayerIndex++)
605+ {
606+ const int32_t kiLayerInTemporal = pEncCtx->uiSpatialLayersInTemporal[iDlayerIndex];
607+ m_pLastSpatialPicture[iDlayerIndex][0] = pEncCtx->pSpatialPic[iDlayerIndex][kiLayerInTemporal - 2];
608+ m_pLastSpatialPicture[iDlayerIndex][1] = NULL;
609+ }
610+ for (; iDlayerIndex<MAX_DEPENDENCY_LAYER; iDlayerIndex++)
611+ {
612+ m_pLastSpatialPicture[iDlayerIndex][0] = m_pLastSpatialPicture[iDlayerIndex][1] = NULL;
613+ }
614+
615+ return 0;
616+}
617+//*********************************************************************************************************/
618+
619+int32_t CWelsPreProcess::ColorspaceConvert(SWelsSvcCodingParam * pSvcParam, SPicture *pDstPic, const SSourcePicture *kpSrc, const int32_t kiWidth, const int32_t kiHeight )
620+{
621+ return 1;
622+ //not support yet
623+}
624+
625+void CWelsPreProcess::BilateralDenoising ( SPicture *pSrc, const int32_t kiWidth, const int32_t kiHeight )
626+{
627+ int32_t iMethodIdx = METHOD_DENOISE;
628+ SPixMap sSrcPixMap = {0};
629+
630+ sSrcPixMap.pPixel[0] = pSrc->pData[0];
631+ sSrcPixMap.pPixel[1] = pSrc->pData[1];
632+ sSrcPixMap.pPixel[2] = pSrc->pData[2];
633+ sSrcPixMap.iSizeInBits = g_kiPixMapSizeInBits;
634+ sSrcPixMap.sRect.iRectWidth = kiWidth;
635+ sSrcPixMap.sRect.iRectHeight = kiHeight;
636+ sSrcPixMap.iStride[0] = pSrc->iLineSize[0];
637+ sSrcPixMap.iStride[1] = pSrc->iLineSize[1];
638+ sSrcPixMap.iStride[2] = pSrc->iLineSize[2];
639+ sSrcPixMap.eFormat = VIDEO_FORMAT_I420;
640+
641+ m_pInterfaceVp->Process(iMethodIdx, &sSrcPixMap, NULL);
642+}
643+
644+bool_t CWelsPreProcess::DetectSceneChange( SPicture *pCurPicture, SPicture *pRefPicture )
645+{
646+ bool_t bSceneChangeFlag = false;
647+ int32_t iMethodIdx = METHOD_SCENE_CHANGE_DETECTION;
648+ SSceneChangeResult sSceneChangeDetectResult = {0};
649+ SPixMap sSrcPixMap = {0};
650+ SPixMap sRefPixMap = {0};
651+
652+ sSrcPixMap.pPixel[0] = pCurPicture->pData[0];
653+ sSrcPixMap.iSizeInBits = g_kiPixMapSizeInBits;
654+ sSrcPixMap.iStride[0] = pCurPicture->iLineSize[0];
655+ sSrcPixMap.sRect.iRectWidth = pCurPicture->iWidthInPixel;
656+ sSrcPixMap.sRect.iRectHeight = pCurPicture->iHeightInPixel;
657+ sSrcPixMap.eFormat = VIDEO_FORMAT_I420;
658+
659+
660+ sRefPixMap.pPixel[0] = pRefPicture->pData[0];
661+ sRefPixMap.iSizeInBits = g_kiPixMapSizeInBits;
662+ sRefPixMap.iStride[0] = pRefPicture->iLineSize[0];
663+ sRefPixMap.sRect.iRectWidth = pRefPicture->iWidthInPixel;
664+ sRefPixMap.sRect.iRectHeight = pRefPicture->iHeightInPixel;
665+ sRefPixMap.eFormat = VIDEO_FORMAT_I420;
666+
667+ int32_t iRet = m_pInterfaceVp->Process(iMethodIdx, &sSrcPixMap, &sRefPixMap);
668+ if (iRet == 0)
669+ {
670+ m_pInterfaceVp->Get(iMethodIdx, (void*)&sSceneChangeDetectResult);
671+ bSceneChangeFlag = sSceneChangeDetectResult.bSceneChangeFlag ? true : false;
672+ }
673+
674+ return bSceneChangeFlag;
675+}
676+
677+int32_t CWelsPreProcess::DownsamplePadding( SPicture *pSrc, SPicture *pDstPic, int32_t iSrcWidth, int32_t iSrcHeight,
678+ int32_t iShrinkWidth, int32_t iShrinkHeight, int32_t iTargetWidth, int32_t iTargetHeight )
679+{
680+ int32_t iRet = 0;
681+ SPixMap sSrcPixMap = {0};
682+ SPixMap sDstPicMap = {0};
683+
684+ sSrcPixMap.pPixel[0] = pSrc->pData[0];
685+ sSrcPixMap.pPixel[1] = pSrc->pData[1];
686+ sSrcPixMap.pPixel[2] = pSrc->pData[2];
687+ sSrcPixMap.iSizeInBits = g_kiPixMapSizeInBits;
688+ sSrcPixMap.sRect.iRectWidth = iSrcWidth;
689+ sSrcPixMap.sRect.iRectHeight = iSrcHeight;
690+ sSrcPixMap.iStride[0] = pSrc->iLineSize[0];
691+ sSrcPixMap.iStride[1] = pSrc->iLineSize[1];
692+ sSrcPixMap.iStride[2] = pSrc->iLineSize[2];
693+ sSrcPixMap.eFormat = VIDEO_FORMAT_I420;
694+
695+ if (iSrcWidth != iShrinkWidth || iSrcHeight != iShrinkHeight)
696+ {
697+ int32_t iMethodIdx = METHOD_DOWNSAMPLE;
698+ sDstPicMap.pPixel[0] = pDstPic->pData[0];
699+ sDstPicMap.pPixel[1] = pDstPic->pData[1];
700+ sDstPicMap.pPixel[2] = pDstPic->pData[2];
701+ sDstPicMap.iSizeInBits = g_kiPixMapSizeInBits;
702+ sDstPicMap.sRect.iRectWidth = iShrinkWidth;
703+ sDstPicMap.sRect.iRectHeight = iShrinkHeight;
704+ sDstPicMap.iStride[0] = pDstPic->iLineSize[0];
705+ sDstPicMap.iStride[1] = pDstPic->iLineSize[1];
706+ sDstPicMap.iStride[2] = pDstPic->iLineSize[2];
707+ sDstPicMap.eFormat = VIDEO_FORMAT_I420;
708+
709+ iRet = m_pInterfaceVp->Process(iMethodIdx, &sSrcPixMap, &sDstPicMap);
710+ }
711+ else
712+ {
713+ memcpy(&sDstPicMap, &sSrcPixMap, sizeof(sDstPicMap)); // confirmed_safe_unsafe_usage
714+ }
715+
716+ // get rid of odd line
717+ iShrinkWidth -= (iShrinkWidth & 1);
718+ iShrinkHeight -= (iShrinkHeight & 1);
719+ Padding( (uint8_t *)sDstPicMap.pPixel[0], (uint8_t *)sDstPicMap.pPixel[1], (uint8_t *)sDstPicMap.pPixel[2],
720+ sDstPicMap.iStride[0], sDstPicMap.iStride[1], iShrinkWidth, iTargetWidth, iShrinkHeight, iTargetHeight);
721+
722+ return iRet;
723+}
724+
725+//*********************************************************************************************************/
726+void CWelsPreProcess::VaaCalculation(SVAAFrameInfo *pVaaInfo, SPicture *pCurPicture, SPicture *pRefPicture,
727+ bool_t bCalculateSQDiff, bool_t bCalculateVar, bool_t bCalculateBGD)
728+{
729+ pVaaInfo->sVaaCalcInfo.pCurY = pCurPicture->pData[0];
730+ pVaaInfo->sVaaCalcInfo.pRefY = pRefPicture->pData[0];
731+ {
732+ int32_t iMethodIdx = METHOD_VAA_STATISTICS;
733+ SPixMap sCurPixMap = {0};
734+ SPixMap sRefPixMap = {0};
735+ SVAACalcParam calc_param = {0};
736+
737+ sCurPixMap.pPixel[0] = pCurPicture->pData[0];
738+ sCurPixMap.iSizeInBits = g_kiPixMapSizeInBits;
739+ sCurPixMap.sRect.iRectWidth = pCurPicture->iWidthInPixel;
740+ sCurPixMap.sRect.iRectHeight = pCurPicture->iHeightInPixel;
741+ sCurPixMap.iStride[0] = pCurPicture->iLineSize[0];
742+ sCurPixMap.eFormat = VIDEO_FORMAT_I420;
743+
744+ sRefPixMap.pPixel[0] = pRefPicture->pData[0];
745+ sRefPixMap.iSizeInBits = g_kiPixMapSizeInBits;
746+ sRefPixMap.sRect.iRectWidth = pRefPicture->iWidthInPixel;
747+ sRefPixMap.sRect.iRectHeight = pRefPicture->iHeightInPixel;
748+ sRefPixMap.iStride[0] = pRefPicture->iLineSize[0];
749+ sRefPixMap.eFormat = VIDEO_FORMAT_I420;
750+
751+ calc_param.iCalcVar = bCalculateVar;
752+ calc_param.iCalcBgd = bCalculateBGD;
753+ calc_param.iCalcSsd = bCalculateSQDiff;
754+ calc_param.pCalcResult = &pVaaInfo->sVaaCalcInfo;
755+
756+ m_pInterfaceVp->Set(iMethodIdx, &calc_param);
757+ m_pInterfaceVp->Process(iMethodIdx, &sCurPixMap, &sRefPixMap);
758+ }
759+}
760+
761+void CWelsPreProcess::BackgroundDetection( SVAAFrameInfo *pVaaInfo, SPicture *pCurPicture, SPicture *pRefPicture, bool_t bDetectFlag )
762+{
763+ if (bDetectFlag)
764+ {
765+ pVaaInfo->iPicWidth = pCurPicture->iWidthInPixel;
766+ pVaaInfo->iPicHeight = pCurPicture->iHeightInPixel;
767+
768+ pVaaInfo->iPicStride = pCurPicture->iLineSize[0];
769+ pVaaInfo->iPicStrideUV = pCurPicture->iLineSize[1];
770+ pVaaInfo->pCurY = pCurPicture->pData[0];
771+ pVaaInfo->pRefY = pRefPicture->pData[0];
772+ pVaaInfo->pCurU = pCurPicture->pData[1];
773+ pVaaInfo->pRefU = pRefPicture->pData[1];
774+ pVaaInfo->pCurV = pCurPicture->pData[2];
775+ pVaaInfo->pRefV = pRefPicture->pData[2];
776+
777+ int32_t iMethodIdx = METHOD_BACKGROUND_DETECTION;
778+ SPixMap sSrcPixMap = {0};
779+ SPixMap sRefPixMap = {0};
780+ SBGDInterface BGDParam = {0};
781+
782+ sSrcPixMap.pPixel[0] = pCurPicture->pData[0];
783+ sSrcPixMap.pPixel[1] = pCurPicture->pData[1];
784+ sSrcPixMap.pPixel[2] = pCurPicture->pData[2];
785+ sSrcPixMap.iSizeInBits = g_kiPixMapSizeInBits;
786+ sSrcPixMap.iStride[0] = pCurPicture->iLineSize[0];
787+ sSrcPixMap.iStride[1] = pCurPicture->iLineSize[1];
788+ sSrcPixMap.iStride[2] = pCurPicture->iLineSize[2];
789+ sSrcPixMap.sRect.iRectWidth = pCurPicture->iWidthInPixel;
790+ sSrcPixMap.sRect.iRectHeight = pCurPicture->iHeightInPixel;
791+ sSrcPixMap.eFormat = VIDEO_FORMAT_I420;
792+
793+ sRefPixMap.pPixel[0] = pRefPicture->pData[0];
794+ sRefPixMap.pPixel[1] = pRefPicture->pData[1];
795+ sRefPixMap.pPixel[2] = pRefPicture->pData[2];
796+ sRefPixMap.iSizeInBits = g_kiPixMapSizeInBits;
797+ sRefPixMap.iStride[0] = pRefPicture->iLineSize[0];
798+ sRefPixMap.iStride[1] = pRefPicture->iLineSize[1];
799+ sRefPixMap.iStride[2] = pRefPicture->iLineSize[2];
800+ sRefPixMap.sRect.iRectWidth = pRefPicture->iWidthInPixel;
801+ sRefPixMap.sRect.iRectHeight = pRefPicture->iHeightInPixel;
802+ sRefPixMap.eFormat = VIDEO_FORMAT_I420;
803+
804+ BGDParam.pBackgroundMbFlag = pVaaInfo->pVaaBackgroundMbFlag;
805+ BGDParam.pCalcRes = &(pVaaInfo->sVaaCalcInfo);
806+ m_pInterfaceVp->Set(iMethodIdx, (void*)&BGDParam);
807+ m_pInterfaceVp->Process(iMethodIdx, &sSrcPixMap, &sRefPixMap);
808+ }
809+ else
810+ {
811+ int32_t iPicWidthInMb = (pCurPicture->iWidthInPixel + 15) >> 4;
812+ int32_t iPicHeightInMb= (pCurPicture->iHeightInPixel+ 15) >> 4;
813+ memset(pVaaInfo->pVaaBackgroundMbFlag, 0, iPicWidthInMb * iPicHeightInMb);
814+ }
815+}
816+
817+void CWelsPreProcess::AdaptiveQuantCalculation( SVAAFrameInfo *pVaaInfo, SPicture *pCurPicture, SPicture *pRefPicture )
818+{
819+ pVaaInfo->sAdaptiveQuantParam.pCalcResult = &(pVaaInfo->sVaaCalcInfo);
820+ pVaaInfo->sAdaptiveQuantParam.dAverMotionTextureIndexToDeltaQp = 0;
821+
822+ {
823+ int32_t iMethodIdx = METHOD_ADAPTIVE_QUANT;
824+ SPixMap pSrc = {0};
825+ SPixMap pRef = {0};
826+ int32_t iRet = 0;
827+
828+ pSrc.pPixel[0] = pCurPicture->pData[0];
829+ pSrc.iSizeInBits = g_kiPixMapSizeInBits;
830+ pSrc.iStride[0] = pCurPicture->iLineSize[0];
831+ pSrc.sRect.iRectWidth = pCurPicture->iWidthInPixel;
832+ pSrc.sRect.iRectHeight = pCurPicture->iHeightInPixel;
833+ pSrc.eFormat = VIDEO_FORMAT_I420;
834+
835+ pRef.pPixel[0] = pRefPicture->pData[0];
836+ pRef.iSizeInBits = g_kiPixMapSizeInBits;
837+ pRef.iStride[0] = pRefPicture->iLineSize[0];
838+ pRef.sRect.iRectWidth = pRefPicture->iWidthInPixel;
839+ pRef.sRect.iRectHeight = pRefPicture->iHeightInPixel;
840+ pRef.eFormat = VIDEO_FORMAT_I420;
841+
842+ iRet = m_pInterfaceVp->Set(iMethodIdx, (void*)&(pVaaInfo->sAdaptiveQuantParam));
843+ iRet = m_pInterfaceVp->Process(iMethodIdx, &pSrc, &pRef);
844+ if (iRet == 0)
845+ m_pInterfaceVp->Get(iMethodIdx, (void*)&(pVaaInfo->sAdaptiveQuantParam));
846+ }
847+}
848+
849+void CWelsPreProcess::SetRefMbType( void *pCtx, uint32_t **pRefMbTypeArray, int32_t iRefPicType )
850+{
851+ sWelsEncCtx *pEncCtx = (sWelsEncCtx *)pCtx;
852+ const uint8_t uiTid = pEncCtx->uiTemporalId;
853+ const uint8_t uiDid = pEncCtx->uiDependencyId;
854+ SRefList *pRefPicLlist = pEncCtx->ppRefPicListExt[uiDid];
855+ SLTRState* pLtr = &pEncCtx->pLtr[uiDid];
856+ uint8_t i = 0;
857+
858+ if (pEncCtx->pSvcParam->bEnableLongTermReference && pLtr->bReceivedT0LostFlag && uiTid == 0)
859+ {
860+ for ( i = 0;i <pRefPicLlist->uiLongRefCount;i++ )
861+ {
862+ SPicture *pRef = pRefPicLlist->pLongRefList[i];
863+ if ( pRef != NULL && pRef->uiRecieveConfirmed == 1/*RECIEVE_SUCCESS*/)
864+ {
865+ *pRefMbTypeArray = pRef->uiRefMbType;
866+ break;
867+ }
868+ }
869+ }
870+ else
871+ {
872+ for ( i = 0; i < pRefPicLlist->uiShortRefCount; i++ )
873+ {
874+ SPicture *pRef = pRefPicLlist->pShortRefList[i];
875+ if ( pRef != NULL && pRef->bUsedAsRef && pRef->iFramePoc >= 0 && pRef->uiTemporalId <= uiTid)
876+ {
877+ *pRefMbTypeArray = pRef->uiRefMbType;
878+ break;
879+ }
880+ }
881+ }
882+}
883+
884+
885+void CWelsPreProcess::AnalyzePictureComplexity( void *pCtx, SPicture *pCurPicture, SPicture *pRefPicture, const int32_t kiDependencyId, const bool_t bCalculateBGD )
886+{
887+ sWelsEncCtx *pEncCtx = (sWelsEncCtx *)pCtx;
888+ SWelsSvcCodingParam *pSvcParam= pEncCtx->pSvcParam;
889+ SVAAFrameInfo *pVaaInfo = pEncCtx->pVaa;
890+
891+ SComplexityAnalysisParam *sComplexityAnalysisParam = &(pVaaInfo->sComplexityAnalysisParam);
892+ SWelsSvcRc *SWelsSvcRc = &pEncCtx->pWelsSvcRc[kiDependencyId];
893+ int32_t iComplexityAnalysisMode = 0;
894+
895+ if( pSvcParam->iRCMode == RC_MODE0 && pEncCtx->eSliceType == P_SLICE )
896+ {
897+ iComplexityAnalysisMode = FRAME_SAD;
898+ }
899+ else if ( pSvcParam->iRCMode == RC_MODE1 && pEncCtx->eSliceType == P_SLICE )
900+ {
901+ iComplexityAnalysisMode = GOM_SAD;
902+ }
903+ else if ( pSvcParam->iRCMode == RC_MODE1 && pEncCtx->eSliceType == I_SLICE )
904+ {
905+ iComplexityAnalysisMode = GOM_VAR;
906+ }
907+ else
908+ {
909+ return;
910+ }
911+
912+ sComplexityAnalysisParam->iComplexityAnalysisMode = iComplexityAnalysisMode;
913+ sComplexityAnalysisParam->pCalcResult = &(pVaaInfo->sVaaCalcInfo);
914+ sComplexityAnalysisParam->pBackgroundMbFlag = pVaaInfo->pVaaBackgroundMbFlag;
915+ SetRefMbType(pEncCtx, &(sComplexityAnalysisParam->uiRefMbType), pRefPicture->iPictureType);
916+ sComplexityAnalysisParam->iCalcBgd = bCalculateBGD;
917+ sComplexityAnalysisParam->iFrameComplexity = 0;
918+
919+ memset(SWelsSvcRc->pGomForegroundBlockNum, 0, SWelsSvcRc->iGomSize*sizeof(int32_t));
920+ if ( iComplexityAnalysisMode != FRAME_SAD )
921+ memset( SWelsSvcRc->pCurrentFrameGomSad, 0, SWelsSvcRc->iGomSize*sizeof(int32_t) );
922+
923+ sComplexityAnalysisParam->pGomComplexity = SWelsSvcRc->pCurrentFrameGomSad;
924+ sComplexityAnalysisParam->pGomForegroundBlockNum = SWelsSvcRc->pGomForegroundBlockNum;
925+ sComplexityAnalysisParam->iMbNumInGom = SWelsSvcRc->iNumberMbGom;
926+
927+ {
928+ int32_t iMethodIdx = METHOD_COMPLEXITY_ANALYSIS;
929+ SPixMap sSrcPixMap = {0};
930+ SPixMap sRefPixMap = {0};
931+ int32_t iRet = 0;
932+
933+ sSrcPixMap.pPixel[0] = pCurPicture->pData[0];
934+ sSrcPixMap.iSizeInBits = g_kiPixMapSizeInBits;
935+ sSrcPixMap.iStride[0] = pCurPicture->iLineSize[0];
936+ sSrcPixMap.sRect.iRectWidth = pCurPicture->iWidthInPixel;
937+ sSrcPixMap.sRect.iRectHeight = pCurPicture->iHeightInPixel;
938+ sSrcPixMap.eFormat = VIDEO_FORMAT_I420;
939+
940+ sRefPixMap.pPixel[0] = pRefPicture->pData[0];
941+ sRefPixMap.iSizeInBits = g_kiPixMapSizeInBits;
942+ sRefPixMap.iStride[0] = pRefPicture->iLineSize[0];
943+ sRefPixMap.sRect.iRectWidth = pRefPicture->iWidthInPixel;
944+ sRefPixMap.sRect.iRectHeight = pRefPicture->iHeightInPixel;
945+ sRefPixMap.eFormat = VIDEO_FORMAT_I420;
946+
947+ iRet = m_pInterfaceVp->Set(iMethodIdx, (void*)sComplexityAnalysisParam);
948+ iRet = m_pInterfaceVp->Process(iMethodIdx, &sSrcPixMap, &sRefPixMap);
949+ if (iRet == 0)
950+ m_pInterfaceVp->Get(iMethodIdx, (void*)sComplexityAnalysisParam);
951+ }
952+}
953+
954+void CWelsPreProcess::Padding(uint8_t * pSrcY, uint8_t * pSrcU, uint8_t * pSrcV, int32_t iStrideY, int32_t iStrideUV,
955+ int32_t iActualWidth, int32_t iPaddingWidth, int32_t iActualHeight, int32_t iPaddingHeight)
956+{
957+ int32_t i;
958+
959+ if( iPaddingHeight > iActualHeight ){
960+ for( i=iActualHeight;i<iPaddingHeight;i++ ){
961+ memset(pSrcY + i*iStrideY, 0, iActualWidth);
962+
963+ if( !(i&1) ){
964+ memset(pSrcU + i/2*iStrideUV, 0x80, iActualWidth/2);
965+ memset(pSrcV + i/2*iStrideUV, 0x80, iActualWidth/2);
966+ }
967+ }
968+ }
969+
970+ if( iPaddingWidth > iActualWidth ){
971+ for( i=0;i<iPaddingHeight;i++ ){
972+ memset(pSrcY + i*iStrideY + iActualWidth, 0, iPaddingWidth - iActualWidth);
973+ if( !(i&1) ){
974+ memset(pSrcU + i/2*iStrideUV + iActualWidth/2, 0x80, (iPaddingWidth - iActualWidth)/2);
975+ memset(pSrcV + i/2*iStrideUV + iActualWidth/2, 0x80, (iPaddingWidth - iActualWidth)/2);
976+ }
977+ }
978+ }
979+}
980+
981+
982+//TODO: may opti later
983+//TODO: not use this func?
984+void * WelsMemcpy( void *dst, const void *kpSrc, uint32_t uiSize)
985+{
986+ return ::memcpy(dst, kpSrc, uiSize);
987+}
988+void * WelsMemset( void * p, int32_t val, uint32_t uiSize)
989+{
990+ return ::memset(p, val, uiSize);
991+}
992+
993+//i420_to_i420_c
994+void WelsMoveMemory_c(uint8_t * pDstY, uint8_t * pDstU, uint8_t * pDstV, int32_t iDstStrideY, int32_t iDstStrideUV,
995+ uint8_t * pSrcY, uint8_t * pSrcU, uint8_t * pSrcV, int32_t iSrcStrideY, int32_t iSrcStrideUV, int32_t iWidth, int32_t iHeight )
996+{
997+ int32_t iWidth2 = iWidth >> 1;
998+ int32_t iHeight2 = iHeight >> 1;
999+ int32_t j;
1000+
1001+ for( j=iHeight;j;j-- )
1002+ {
1003+ WelsMemcpy(pDstY, pSrcY, iWidth);
1004+ pDstY += iDstStrideY;
1005+ pSrcY += iSrcStrideY;
1006+ }
1007+
1008+ for( j=iHeight2;j;j-- )
1009+ {
1010+ WelsMemcpy(pDstU, pSrcU, iWidth2);
1011+ WelsMemcpy(pDstV, pSrcV, iWidth2);
1012+ pDstU += iDstStrideUV;
1013+ pDstV += iDstStrideUV;
1014+ pSrcU += iSrcStrideUV;
1015+ pSrcV += iSrcStrideUV;
1016+ }
1017+}
1018+//vp's padding
1019+void VPpadding(uint8_t * pSrcPtr, int32_t iCurWidth, int32_t iTargetWidth, int32_t iCurHeight, int32_t iTargetHeight,
1020+ int32_t iStride, uint8_t uiStuffValue)
1021+{
1022+ uint8_t *pTmp;
1023+ if( iTargetWidth > iCurWidth )
1024+ {
1025+ pTmp = pSrcPtr + iCurWidth;
1026+ for( int32_t i = 0; i < iCurHeight; i++ )
1027+ {
1028+ WelsMemset(pTmp, uiStuffValue, iTargetWidth - iCurWidth);
1029+ pTmp += iStride;
1030+ }
1031+ }
1032+
1033+ if( iTargetHeight > iCurHeight )
1034+ {
1035+ pTmp = pSrcPtr + iCurHeight * iStride;
1036+ for( int32_t i = iCurHeight; i < iTargetHeight;i++ )
1037+ {
1038+ WelsMemset(pTmp, uiStuffValue, iTargetWidth);
1039+ pTmp += iStride;
1040+ }
1041+ }
1042+}
1043+
1044+
1045+void CWelsPreProcess::WelsMoveMemoryWrapper(SWelsSvcCodingParam * pSvcParam, SPicture *pDstPic, const SSourcePicture *kpSrc,
1046+ const int32_t kiTargetWidth, const int32_t kiTargetHeight )
1047+{
1048+ if (VIDEO_FORMAT_I420!=(kpSrc->iColorFormat & (~VIDEO_FORMAT_VFlip)))
1049+ return;
1050+
1051+ int32_t iSrcWidth = kpSrc->iPicWidth;
1052+ int32_t iSrcHeight = kpSrc->iPicHeight;
1053+
1054+ if ( iSrcHeight > kiTargetHeight ) iSrcHeight = kiTargetHeight;
1055+ if ( iSrcWidth > kiTargetWidth ) iSrcWidth = kiTargetWidth;
1056+
1057+ // copy from fr26 to fix the odd uiSize failed issue
1058+ if( iSrcWidth & 0x1 ) -- iSrcWidth;
1059+ if( iSrcHeight & 0x1 ) -- iSrcHeight;
1060+
1061+ const int32_t kiSrcTopOffsetY = pSvcParam->SUsedPicRect.iTop;
1062+ const int32_t kiSrcTopOffsetUV = (kiSrcTopOffsetY>>1);
1063+ const int32_t kiSrcLeftOffsetY = pSvcParam->SUsedPicRect.iLeft;
1064+ const int32_t kiSrcLeftOffsetUV = (kiSrcLeftOffsetY>>1);
1065+ int32_t iSrcOffset[3] = {0,0,0};
1066+ iSrcOffset[0] = kpSrc->iStride[0]*kiSrcTopOffsetY + kiSrcLeftOffsetY;
1067+ iSrcOffset[1] = kpSrc->iStride[1]*kiSrcTopOffsetUV + kiSrcLeftOffsetUV ;
1068+ iSrcOffset[2] = kpSrc->iStride[2]*kiSrcTopOffsetUV + kiSrcLeftOffsetUV;
1069+
1070+ uint8_t * pSrcY = kpSrc->pData[0] + iSrcOffset[0];
1071+ uint8_t * pSrcU = kpSrc->pData[1] + iSrcOffset[1];
1072+ uint8_t * pSrcV = kpSrc->pData[2] + iSrcOffset[2];
1073+ const int32_t kiSrcStrideY = kpSrc->iStride[0];
1074+ const int32_t kiSrcStrideUV= kpSrc->iStride[1];
1075+
1076+ uint8_t * pDstY = pDstPic->pData[0];
1077+ uint8_t * pDstU = pDstPic->pData[1];
1078+ uint8_t * pDstV = pDstPic->pData[2];
1079+ const int32_t kiDstStrideY = pDstPic->iLineSize[0];
1080+ const int32_t kiDstStrideUV = pDstPic->iLineSize[1];
1081+
1082+#define MAX_WIDTH (4096)
1083+#define MAX_HEIGHT (2304)//MAX_FS_LEVEL51 (36864); MAX_FS_LEVEL51*256/4096 = 2304
1084+ if (pSrcY)
1085+ {
1086+ if (iSrcWidth <= 0 || iSrcWidth > MAX_WIDTH || iSrcHeight <= 0 || iSrcHeight > MAX_HEIGHT)
1087+ return;
1088+ if (kiSrcTopOffsetY >= iSrcHeight || kiSrcLeftOffsetY>= iSrcWidth || iSrcWidth > kiSrcStrideY )
1089+ return;
1090+ }
1091+ if (pDstY)
1092+ {
1093+ if (kiTargetWidth <= 0 || kiTargetWidth > MAX_WIDTH || kiTargetHeight<= 0 || kiTargetHeight> MAX_HEIGHT)
1094+ return;
1095+ if (kiTargetWidth > kiDstStrideY)
1096+ return;
1097+ }
1098+
1099+ if (pSrcY == NULL || pSrcU == NULL || pSrcV == NULL || pDstY == NULL || pDstU == NULL || pDstV == NULL
1100+ || (iSrcWidth & 1) || (iSrcHeight & 1) )
1101+ {}
1102+ else
1103+ {
1104+ //i420_to_i420_c
1105+ WelsMoveMemory_c( pDstY, pDstU, pDstV, kiDstStrideY, kiDstStrideUV,
1106+ pSrcY, pSrcU, pSrcV, kiSrcStrideY, kiSrcStrideUV, iSrcWidth, iSrcHeight );
1107+
1108+ //in VP Process
1109+ if ( kiTargetWidth > iSrcWidth || kiTargetHeight > iSrcHeight )
1110+ {
1111+ const int32_t kiTargetWidthC = (kiTargetWidth>>1);
1112+ const int32_t kiTargetHeightC = (kiTargetHeight>>1);
1113+ const int32_t kiSrcWidthC = (iSrcWidth>>1);
1114+ const int32_t kiSrcHeightC = (iSrcHeight>>1);
1115+
1116+ // padding pDstPic I420
1117+ VPpadding((uint8_t *)pDstY, iSrcWidth, kiTargetWidth, iSrcHeight, kiTargetHeight, kiDstStrideY, 0);
1118+ VPpadding((uint8_t *)pDstU, kiSrcWidthC, kiTargetWidthC, kiSrcHeightC, kiTargetHeightC, kiDstStrideUV, 0x80);
1119+ VPpadding((uint8_t *)pDstV, kiSrcWidthC, kiTargetWidthC, kiSrcHeightC, kiTargetHeightC, kiDstStrideUV, 0x80);
1120+ }
1121+ }
1122+
1123+}
1124+
1125+//*********************************************************************************************************/
1126+} // namespace WelsSVCEnc

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t