X265时域分层编码结构(LDP)实践(附交流群和代码获取方式)

17 篇文章 0 订阅
8 篇文章 1 订阅

关键变量

maxNumReferences:最大参考帧数量
m_rps:参考帧集合
m_numRefIdx:参考列表中的参考帧数量
m_dpb:解码缓存帧列表

关键函数

修改picList的函数

// 遍历m_picList中的所有m_bHasReferences==true的帧
// 根据是否还有参考帧确定这一帧之后是否要扔掉
// 判断方式是,看这一帧在不在m_rps里面
void DPB::applyReferencePictureSet(RPS *rps, int curPoc){
	// loop through all pictures in the reference picture buffer
    Frame* iterFrame = m_picList.first();
    while (iterFrame)
    {
        if (iterFrame->m_poc != curPoc && iterFrame->m_encData->m_bHasReferences)
        {
            bool referenced = false;
            for (int i = 0; i < rps->numberOfPositivePictures + rps->numberOfNegativePictures; i++)
            {
                if (iterFrame->m_poc == curPoc + rps->deltaPOC[i])
                {
                    referenced = true;
                    break;
                }
            }
            if (!referenced)
                iterFrame->m_encData->m_bHasReferences = false;
        }
        iterFrame = iterFrame->m_next;
    }
};

修改rps的函数

// 根据picList中的帧来构建 m_rps
// 要求picList中的帧
// 1. m_bHasReferences == 1
// 2. 
void DPB::computeRPS(int curPoc, bool isRAP, RPS * rps, unsigned int maxDecPicBuffer)
{
    unsigned int poci = 0, numNeg = 0, numPos = 0;
    Frame* iterPic = m_picList.first();

    while (iterPic && (poci < maxDecPicBuffer - 1))
    {
        if ((iterPic->m_poc != curPoc) && iterPic->m_encData->m_bHasReferences)
        {
        	// 当前帧是I 帧或当前帧是B帧
        	// 或者 iterPic 在I帧之后(应该指的是IDR清除缓存帧列表)
            if ((m_lastIDR >= curPoc) || (m_lastIDR <= iterPic->m_poc))
            {
                    rps->poc[poci] = iterPic->m_poc;
                    rps->deltaPOC[poci] = rps->poc[poci] - curPoc;
                    (rps->deltaPOC[poci] < 0) ? numNeg++ : numPos++;
                    rps->bUsed[poci] = !isRAP;
                    poci++;
            }
        }
        iterPic = iterPic->m_next;
    }

    rps->numberOfPictures = poci;
    rps->numberOfPositivePictures = numPos;
    rps->numberOfNegativePictures = numNeg;

    rps->sortDeltaPOC();
}
// 冒泡排序,将RPS中的帧按照从小到大的顺序排序
// 其实也就是,将参考帧按照由近到远的距离排序
// 示例 -1 -2 -3 -4 1 2 3 4  
void RPS::sortDeltaPOC()
{
    for (int j = 1; j < numberOfPictures; j++)
    {
        int dPOC = deltaPOC[j];
        bool used = bUsed[j];
        for (int k = j - 1; k >= 0; k--)
        {
            int temp = deltaPOC[k];
            if (dPOC < temp)
            {
                deltaPOC[k + 1] = temp;
                bUsed[k + 1] = bUsed[k];
                deltaPOC[k] = dPOC;
                bUsed[k] = used;
            }
        }
    }
    int numNegPics = numberOfNegativePictures;
    for (int j = 0, k = numNegPics - 1; j < numNegPics >> 1; j++, k--)
    {
        int dPOC = deltaPOC[j];
        bool used = bUsed[j];
        deltaPOC[j] = deltaPOC[k];
        bUsed[j] = bUsed[k];
        deltaPOC[k] = dPOC;
        bUsed[k] = used;
    }
}

picList和m_rps处理顺序

  1. picList把当前编码帧放进去
  2. 遍历picList,根据m_bHasReferences和m_lastIDR(是否在清空缓存帧列表中)的关系决定是否加入rps
  3. 对rps进行排序
  4. 对picList中的帧进行m_bHasReferences重判断,判断方式是看在不在当前帧的参考列表中,不在的话说明将要被移出去了
  5. 将rps中的帧移入到refPicSetStCurr0、refPicSetStCurr1和refPicSetLtCurr中

LDP实现思路

rps构造修改

原X265-rps构造构造的思想

取picList中可用的、最近的maxNumReferences个参考帧

现LDP-rps构造构造的思想

取picList中可用的、最近的1个参考帧以及一个关键帧,如前一帧已是关键帧,则额外取一关键帧

picList构造修改

原X265-picList丢帧思想

在当前帧未作为参考,则今后不可能再作为参考

现LDP-picList丢帧思想

在当前帧未作为参考的非关键帧,则今后不可能再作为参考
距离当前帧距离超过10的关键帧,则今后不可能再作为参考

参考列表长度管理

根据编码的preset和当前帧的GOP位置进行调整

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值