x265-确定slice type-3

这篇博客详细解析了x265编码器中slicetypeDecide方法的调用流程,包括PreLookaheadGroup的创建、低分辨率图像的初始化和处理,以及不同自适应量化(AQ)模式的实现,如None、HEVC AQ、Auto Variance等。通过分析lowers的create方法和calcAdaptiveQuantFrame,展示了如何根据帧的活动度调整量化参数以优化编码质量。

下面分析slicetypeDecide的方法的调用:

1.创建PreLookaheadGroup,主要的功能是

PreLookaheadGroup pre(*this);

下面是获取输入列表中,bframes+2个帧到list链表中:

int j;
        for (j = 0; j < m_param->bframes + 2; j++)
        {
            if (!curFrame) break;
            list[j] = curFrame;
            curFrame = curFrame->m_next;
        }
下面的这段代码的功能是:

frames数组中,第一个位置保持上一个非B帧,后续保存当前输入queue中,maxsearch个帧的低分辨率图像。

如果m_lowresInit为false的话,并把这些低分辨率的图像设置到了preLookahead中:

curFrame = m_inputQueue.first();
        frames[0] = m_lastNonB;
        for (j = 0; j < maxSearch; j++)
        {
            if (!curFrame) break;
            frames[j + 1] = &curFrame->m_lowres;

            if (!curFrame->m_lowresInit)
                pre.m_preframes[pre.m_jobTotal++] = curFrame;

            curFrame = curFrame->m_next;
        }

        maxSearch = j;

下面进行的PreLookaheadGroup中task的执行:

if (pre.m_jobTotal)
    {
        if (m_pool)
            pre.tryBondPeers(*m_pool, pre.m_jobTotal);
        pre.processTasks(-1);
        pre.waitForExit();
    }

processTasks其中的关键调用如下:

        preFrame->m_lowres.init(preFrame->m_fencPic, preFrame->m_poc);
        if (m_lookahead.m_bAdaptiveQuant)
            tld.calcAdaptiveQuantFrame(preFrame, m_lookahead.m_param);
        tld.lowresIntraEstimate(preFrame->m_lowres, m_lookahead.m_param->rc.qgSize);

1.1 先分析lowers的create方法(lowers.cpp中)

isLowres = true;
    bframes = param->bframes;
    widthFullRes = origPic->m_picWidth;
    heightFullRes = origPic->m_picHeight;
    width = origPic->m_picWidth / 2;//宽高都为元图像的一般
    lines = origPic->m_picHeight / 2;
    bEnableHME = param->bEnableHME ? 1 : 0;
    lumaStride = width + 2 * origPic->m_lumaMarginX;//lumastride为32对齐的宽度
    if (lumaStride & 31)
        lumaStride += 32 - (lumaStride & 31);
    maxBlocksInRow = (width + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;//以8x8,计算row和col的block的数目
    maxBlocksInCol = (lines + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;
    maxBlocksInRowFullRes = maxBlocksInRow * 2;
    maxBlocksInColFullRes = maxBlocksInCol * 2;
    int cuCount = maxBlocksInRow * maxBlocksInCol;//计算cu的数目

/*

/* Enable adaptive quantization at CU granularity. This parameter specifies
         * the minimum CU size at which QP can be adjusted, i.e. Quantization Group
         * (QG) size. Allowed values are 64, 32, 16, 8 provided it falls within the
         * inclusuve range [maxCUSize, minCUSize]. Experimental, default: maxCUSize */
        uint32_t qgSize;//表示的进行adaptive qutization的最小的cu size

*/
    int cuCountFullRes = (qgSize > 8) ? cuCount : cuCount << 2;

/*
    /* Enable 3-level Hierarchical motion estimation at One-Sixteenth, Quarter and Full resolution.
     * Default is disabled */
    int       bEnableHME;

*/
    isHMELowres = param->bEnableHME ? 1 : 0;
    size_t planesize = lumaStride * (lines + 2 * origPic->m_lumaMarginY);
    size_t padoffset = lumaStride * origPic->m_lumaMarginY + origPic->m_lumaMarginX;

如果开启了AQ quatization,初始化了一系列的矩阵,qpAqOffset,invQscaleFactor,qpCuTreeOffset,invQscaleFactor8x8,qpAqMotionOffset,blockVariance,

如果是HEVCAQ,分为了4个层级,如果maxCUSize是64,这ctuSizeIdx为0;

 if (!!param->rc.hevcAq)
    {
        m_maxCUSize = param->maxCUSize;
        m_qgSize = qgSize;

        uint32_t partWidth, partHeight, nAQPartInWidth, nAQPartInHeight;

        pAQLayer = new PicQPAdaptationLayer[4];
        maxAQDepth = 0;
        for (uint32_t d = 0; d < 4; d++)
        {
            int ctuSizeIdx = 6 - g_log2Size[param->maxCUSize];
            int aqDepth = g_log2Size[param->maxCUSize] - g_log2Size[qgSize];
            if (!aqLayerDepth[ctuSizeIdx][aqDepth][d])
                continue;

            pAQLayer->minAQDepth = d;
            partWidth = param->maxCUSize >> d;
            partHeight = param->maxCUSize >> d;

            if (minAQSize[ctuSizeIdx] == d)//刚好和最大CUsize相同的一级
            {
                pAQLayer[d].bQpSize = true;
                nAQPartInWidth = maxBlocksInRow * 2;
                nAQPartInHeight = maxBlocksInCol * 2;
            }
            else
            {
                pAQLayer[d].bQpSize = false;
                nAQPartInWidth = (origPic->m_picWidth + partWidth - 1) / partWidth;
                nAQPartInHeight = (origPic->m_picHeight + partHeight - 1) / partHeight;
            }

以上计算了AQ模式下的width和height;

            maxAQDepth++;

/*

dActivity,dQpOffset,dCuTreeOffset,dCuTreeOffset8x8

*/

            pAQLayer[d].create(origPic->m_picWidth, origPic->m_picHeight, partWidth, partHeight, nAQPartInWidth, nAQPartInHeight);
        }
    }

 

 buffer[1] = buffer[0] + planesize;
    buffer[2] = buffer[1] + planesize;
    buffer[3] = buffer[2] + planesize;

    lowresPlane[0] = buffer[0] + padoffset;
    lowresPlane[1] = buffer[1] + padoffset;
    lowresPlane[2] = buffer[2] + padoffset;
    lowresPlane[3] = buffer[3] + padoffset;

初始化了rowSatds,lowresCosts,lowresMvs,lowresMvCosts;

1.2:preFrame->m_lowres.init

/* downscale and generate 4 hpel planes for lookahead */
    primitives.frameInitLowres(origPic->m_picOrg[0],
                               lowresPlane[0], lowresPlane[1], lowresPlane[2], lowresPlane[3],
                               origPic->m_stride, lumaStride, width, lines);

其中frameInitLowres是pixel.cpp中的frame_init_lowres_core。

扩展上下margin:

extendPicBorder(lowresPlane[0], lumaStride, width, lines, origPic->m_lumaMarginX, origPic->m_lumaMarginY);

1.3 calcAdaptiveQuantFrame的分析

//最大的行和列

int maxCol = curFrame->m_fencPic->m_picWidth;
    int maxRow = curFrame->m_fencPic->m_picHeight;

//初始化,wp_ssd,wp_sum

 for (int y = 0; y < 3; y++)
    {
        curFrame->m_lowres.wp_ssd[y] = 0;
        curFrame->m_lowres.wp_sum[y] = 0;
    }

case 1: param->rc.aqMode == X265_AQ_NONE || param->rc.aqStrength == 0

qpCuTreeOffset和qpAqOffset,被初始化为0

invQscaleFactor,被初始化为256

case 2:param->rc.hevcAq

/*
         * Enable adaptive quantization.
         * It scales the quantization step size according to the spatial activity of one
         * coding unit relative to frame average spatial activity. This AQ method utilizes
         * the minimum variance(方差) of sub-unit in each coding unit to represent the coding
         * unit’s spatial complexity. */

// New method for calculating variance and qp offset
                xPreanalyze(curFrame);调用它

分析xPreanalyze:

 

case 3:param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED

 

case 4:param->rc.aqMode == X265_AQ_AUTO_VARIANCE

 

case 5:param->rc.aqMode == X265_AQ_EDGE

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值