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
54namespace WelsSVCEnc {
55
56#define WelsSafeDelete(p) if(p){ delete (p); (p) = NULL; }
57
58//***** entry API declaration ************************************************************************//
59typedef EResult (WELSAPI *pfnCreateVpInterface) (void **, int );
60typedef EResult (WELSAPI *pfnDestroyVpInterface) (void * , int );
61
62int32_t WelsInitScaledPic( SWelsSvcCodingParam *pParam, Scaled_Picture *pScaledPic, CMemoryAlign *pMemoryAlign );
63bool_t JudgeNeedOfScaling( SWelsSvcCodingParam *pParam, Scaled_Picture * pScaledPic );
64void FreeScaledPic( Scaled_Picture *pScaledPic, CMemoryAlign *pMemoryAlign );
65
66//******* table definition ***********************************************************************//
67const 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
76const int32_t g_kiPixMapSizeInBits = sizeof(uint8_t) * 8;
77
78
79inline 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//***************************************************************************************************//
87CWelsLib::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
116CWelsLib::~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
136void* 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
159int32_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
182int32_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
205CWelsPreProcess::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
215CWelsPreProcess::~CWelsPreProcess()
216{
217 FreeScaledPic(&m_sScaledPicture, static_cast<sWelsEncCtx *>(m_pEncCtx)->pMemAlign);
218 WelsPreprocessDestroy();
219}
220
221int32_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
238exit:
239 WelsPreprocessDestroy();
240 return 1;
241}
242
243int32_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
255int32_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
270int32_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
327int32_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*/
378int32_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
488int32_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 */
539bool_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
576int32_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
588void FreeScaledPic(Scaled_Picture *pScaledPicture, CMemoryAlign *pMemoryAlign)
589{
590 if ( pScaledPicture->pScaledInputPicture )
591 {
592 FreePicture( pMemoryAlign, &pScaledPicture->pScaledInputPicture );
593 pScaledPicture->pScaledInputPicture = NULL;
594 }
595}
596
597int32_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
619int32_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
625void 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
644bool_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
677int32_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//*********************************************************************************************************/
726void 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
761void 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
817void 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
849void 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
885void 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
954void 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?
984void * WelsMemcpy( void *dst, const void *kpSrc, uint32_t uiSize)
985{
986 return ::memcpy(dst, kpSrc, uiSize);
987}
988void * WelsMemset( void * p, int32_t val, uint32_t uiSize)
989{
990 return ::memset(p, val, uiSize);
991}
992
993//i420_to_i420_c
994void 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
1019void 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
1045void 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