Normally, the DownsamplePadding skips scaling if the target size is the same as the source size, assuming that the caller will use the source data pointer in that case. This is true for the base layer (the first call to DownsamplePadding in SingleLayerPreprocess), but when downsampling the other layers, there is no special handling for the case when the target is the same size as the source. Previously, the encoding of such spatial layers will use completely uninitialized data, encoding complete garbage. Instead force DownsamplePadding to make a copy if no scaling is required, for the dependency layers. The base layer still avoids a copy unless scaling of that layer is required. Whether it actually makes sense to have lower spatial layers the same size as the original one is a different question though - currently the code allows it, and EncodeDecodeTestAPI.SetOptionEncParamExt will try to use it.
Showing the changes to codec/encoder/core/src/wels_preprocess.cpp (1 of 2 files). Show all
Unified · Split
| @@ -45,6 +45,9 @@ namespace WelsEnc { · 44 unmodified lines | |||
| 45 | int32_t WelsInitScaledPic (SWelsSvcCodingParam* pParam, Scaled_Picture* pScaledPic, CMemoryAlign* pMemoryAlign); | 45 | int32_t WelsInitScaledPic (SWelsSvcCodingParam* pParam, Scaled_Picture* pScaledPic, CMemoryAlign* pMemoryAlign); |
| 46 | bool JudgeNeedOfScaling (SWelsSvcCodingParam* pParam, Scaled_Picture* pScaledPic); | 46 | bool JudgeNeedOfScaling (SWelsSvcCodingParam* pParam, Scaled_Picture* pScaledPic); |
| 47 | void FreeScaledPic (Scaled_Picture* pScaledPic, CMemoryAlign* pMemoryAlign); | 47 | void FreeScaledPic (Scaled_Picture* pScaledPic, CMemoryAlign* pMemoryAlign); |
| 48 | void WelsMoveMemory_c (uint8_t* pDstY, uint8_t* pDstU, uint8_t* pDstV, int32_t iDstStrideY, int32_t iDstStrideUV, | ||
| 49 | uint8_t* pSrcY, uint8_t* pSrcU, uint8_t* pSrcV, int32_t iSrcStrideY, int32_t iSrcStrideUV, int32_t iWidth, | ||
| 50 | int32_t iHeight); | ||
| 48 | 51 | ||
| 49 | //******* table definition ***********************************************************************// | 52 | //******* table definition ***********************************************************************// |
| 50 | const uint8_t g_kuiRefTemporalIdx[MAX_TEMPORAL_LEVEL][MAX_GOP_SIZE] = { | 53 | const uint8_t g_kuiRefTemporalIdx[MAX_TEMPORAL_LEVEL][MAX_GOP_SIZE] = { |
| @@ -329,7 +332,7 @@ int32_t CWelsPreProcess::SingleLayerPreprocess (sWelsEncCtx* pCtx, const SSource · 278 unmodified lines | |||
| 329 | iShrinkWidth = pScaledPicture->iScaledWidth[iDependencyId]; | 332 | iShrinkWidth = pScaledPicture->iScaledWidth[iDependencyId]; |
| 330 | iShrinkHeight = pScaledPicture->iScaledHeight[iDependencyId]; | 333 | iShrinkHeight = pScaledPicture->iScaledHeight[iDependencyId]; |
| 331 | } | 334 | } |
| 332 | DownsamplePadding (pSrcPic, pDstPic, iSrcWidth, iSrcHeight, iShrinkWidth, iShrinkHeight, iTargetWidth, iTargetHeight); | 335 | DownsamplePadding (pSrcPic, pDstPic, iSrcWidth, iSrcHeight, iShrinkWidth, iShrinkHeight, iTargetWidth, iTargetHeight, false); |
| 333 | 336 | ||
| 334 | if (pSvcParam->bEnableSceneChangeDetect && !pCtx->pVaa->bIdrPeriodFlag) { | 337 | if (pSvcParam->bEnableSceneChangeDetect && !pCtx->pVaa->bIdrPeriodFlag) { |
| 335 | if (pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) { | 338 | if (pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) { |
| @@ -384,7 +387,7 @@ int32_t CWelsPreProcess::SingleLayerPreprocess (sWelsEncCtx* pCtx, const SSource · 48 unmodified lines | |||
| 384 | pDstPic = m_pSpatialPic[iDependencyId][iPicturePos]; // small | 387 | pDstPic = m_pSpatialPic[iDependencyId][iPicturePos]; // small |
| 385 | iShrinkWidth = pScaledPicture->iScaledWidth[iDependencyId]; | 388 | iShrinkWidth = pScaledPicture->iScaledWidth[iDependencyId]; |
| 386 | iShrinkHeight = pScaledPicture->iScaledHeight[iDependencyId]; | 389 | iShrinkHeight = pScaledPicture->iScaledHeight[iDependencyId]; |
| 387 | DownsamplePadding (pSrcPic, pDstPic, iSrcWidth, iSrcHeight, iShrinkWidth, iShrinkHeight, iTargetWidth, iTargetHeight); | 390 | DownsamplePadding (pSrcPic, pDstPic, iSrcWidth, iSrcHeight, iShrinkWidth, iShrinkHeight, iTargetWidth, iTargetHeight, true); |
| 388 | 391 | ||
| 389 | WelsUpdateSpatialIdxMap (pCtx, iActualSpatialLayerNum - 1, pDstPic, iDependencyId); | 392 | WelsUpdateSpatialIdxMap (pCtx, iActualSpatialLayerNum - 1, pDstPic, iDependencyId); |
| 390 | 393 | ||
| @@ -534,7 +537,7 @@ bool CWelsPreProcess::DetectSceneChange (SPicture* pCurPicture, SPicture* pRefPi · 143 unmodified lines | |||
| 534 | } | 537 | } |
| 535 | 538 | ||
| 536 | int32_t CWelsPreProcess::DownsamplePadding (SPicture* pSrc, SPicture* pDstPic, int32_t iSrcWidth, int32_t iSrcHeight, | 539 | int32_t CWelsPreProcess::DownsamplePadding (SPicture* pSrc, SPicture* pDstPic, int32_t iSrcWidth, int32_t iSrcHeight, |
| 537 | int32_t iShrinkWidth, int32_t iShrinkHeight, int32_t iTargetWidth, int32_t iTargetHeight) { | 540 | int32_t iShrinkWidth, int32_t iShrinkHeight, int32_t iTargetWidth, int32_t iTargetHeight, bool bForceCopy) { |
| 538 | int32_t iRet = 0; | 541 | int32_t iRet = 0; |
| 539 | SPixMap sSrcPixMap; | 542 | SPixMap sSrcPixMap; |
| 540 | SPixMap sDstPicMap; | 543 | SPixMap sDstPicMap; |
| @@ -551,7 +554,7 @@ int32_t CWelsPreProcess::DownsamplePadding (SPicture* pSrc, SPicture* pDstPic, · 10 unmodified lines | |||
| 551 | sSrcPixMap.iStride[2] = pSrc->iLineSize[2]; | 554 | sSrcPixMap.iStride[2] = pSrc->iLineSize[2]; |
| 552 | sSrcPixMap.eFormat = VIDEO_FORMAT_I420; | 555 | sSrcPixMap.eFormat = VIDEO_FORMAT_I420; |
| 553 | 556 | ||
| 554 | if (iSrcWidth != iShrinkWidth || iSrcHeight != iShrinkHeight) { | 557 | if (iSrcWidth != iShrinkWidth || iSrcHeight != iShrinkHeight || bForceCopy) { |
| 555 | int32_t iMethodIdx = METHOD_DOWNSAMPLE; | 558 | int32_t iMethodIdx = METHOD_DOWNSAMPLE; |
| 556 | sDstPicMap.pPixel[0] = pDstPic->pData[0]; | 559 | sDstPicMap.pPixel[0] = pDstPic->pData[0]; |
| 557 | sDstPicMap.pPixel[1] = pDstPic->pData[1]; | 560 | sDstPicMap.pPixel[1] = pDstPic->pData[1]; |
| @@ -564,7 +567,13 @@ int32_t CWelsPreProcess::DownsamplePadding (SPicture* pSrc, SPicture* pDstPic, · 6 unmodified lines | |||
| 564 | sDstPicMap.iStride[2] = pDstPic->iLineSize[2]; | 567 | sDstPicMap.iStride[2] = pDstPic->iLineSize[2]; |
| 565 | sDstPicMap.eFormat = VIDEO_FORMAT_I420; | 568 | sDstPicMap.eFormat = VIDEO_FORMAT_I420; |
| 566 | 569 | ||
| 567 | iRet = m_pInterfaceVp->Process (iMethodIdx, &sSrcPixMap, &sDstPicMap); | 570 | if (iSrcWidth != iShrinkWidth || iSrcHeight != iShrinkHeight) { |
| 571 | iRet = m_pInterfaceVp->Process (iMethodIdx, &sSrcPixMap, &sDstPicMap); | ||
| 572 | } else { | ||
| 573 | WelsMoveMemory_c (pDstPic->pData[0], pDstPic->pData[1], pDstPic->pData[2], pDstPic->iLineSize[0], pDstPic->iLineSize[1], | ||
| 574 | pSrc->pData[0], pSrc->pData[1], pSrc->pData[2], pSrc->iLineSize[0], pSrc->iLineSize[1], | ||
| 575 | iSrcWidth, iSrcHeight); | ||
| 576 | } | ||
| 568 | } else { | 577 | } else { |
| 569 | memcpy (&sDstPicMap, &sSrcPixMap, sizeof (sDstPicMap)); // confirmed_safe_unsafe_usage | 578 | memcpy (&sDstPicMap, &sSrcPixMap, sizeof (sDstPicMap)); // confirmed_safe_unsafe_usage |
| 570 | } | 579 | } |