文章目录
关键变量
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处理顺序
- picList把当前编码帧放进去
- 遍历picList,根据m_bHasReferences和m_lastIDR(是否在清空缓存帧列表中)的关系决定是否加入rps
- 对rps进行排序
- 对picList中的帧进行m_bHasReferences重判断,判断方式是看在不在当前帧的参考列表中,不在的话说明将要被移出去了
- 将rps中的帧移入到refPicSetStCurr0、refPicSetStCurr1和refPicSetLtCurr中
LDP实现思路
rps构造修改
原X265-rps构造构造的思想
取picList中可用的、最近的maxNumReferences个参考帧
现LDP-rps构造构造的思想
取picList中可用的、最近的1个参考帧以及一个关键帧,如前一帧已是关键帧,则额外取一关键帧
picList构造修改
原X265-picList丢帧思想
在当前帧未作为参考,则今后不可能再作为参考
现LDP-picList丢帧思想
在当前帧未作为参考的非关键帧,则今后不可能再作为参考
距离当前帧距离超过10的关键帧,则今后不可能再作为参考
参考列表长度管理
根据编码的preset和当前帧的GOP位置进行调整