注:问号以及未注释部分 会在x265-1.9版本内更新

/*****************************************************************************
* Copyright (C) 2013 x265 project
*
* Authors: Steve Borho <steve@borho.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
*
* This program is also available under a commercial proprietary license.
* For more information, contact us at license @ x265.com.
*****************************************************************************/
#include "common.h"
#include "frame.h"
#include "framedata.h"
#include "picyuv.h"
#include "slice.h"
#include "dpb.h"
using namespace X265_NS;
DPB::~DPB()
{
while (!m_freeList.empty())
{
Frame* curFrame = m_freeList.popFront();
curFrame->destroy();
delete curFrame;
}
while (!m_picList.empty())
{
Frame* curFrame = m_picList.popFront();
curFrame->destroy();
delete curFrame;
}
while (m_picSymFreeList)
{
FrameData* next = m_picSymFreeList->m_freeListNext;
m_picSymFreeList->destroy();
m_picSymFreeList->m_reconPic->destroy();
delete m_picSymFreeList->m_reconPic;
delete m_picSymFreeList;
m_picSymFreeList = next;
}
}
// move unreferenced pictures from picList to freeList for recycle
void DPB::recycleUnreferenced()
{
Frame *iterFrame = m_picList.first();
while (iterFrame)
{
Frame *curFrame = iterFrame;
iterFrame = iterFrame->m_next;
if (!curFrame->m_encData->m_bHasReferences && !curFrame->m_countRefEncoders)
{
curFrame->m_reconRowCount.set(0);
curFrame->m_bChromaExtended = false;
// iterator is invalidated by remove, restart scan
m_picList.remove(*curFrame);
iterFrame = m_picList.first();
m_freeList.pushBack(*curFrame);
curFrame->m_encData->m_freeListNext = m_picSymFreeList;
m_picSymFreeList = curFrame->m_encData;
curFrame->m_encData = NULL;
curFrame->m_reconPic = NULL;
}
}
}
/** 函数功能       : 设置NAL单元类型,将待编码帧加入DPB列表,获取slice参考帧列表等slice参量,将该帧的参考帧的被参考次数加一
/*  调用范围       : 只在Encoder::encode函数中被调用
* \参数 newFrame   : 待编码帧
*   返回值         : null
**/
void DPB::prepareEncode(Frame *newFrame)
{
Slice* slice = newFrame->m_encData->m_slice;//获取当前frame的slice
slice->m_poc = newFrame->m_poc;//设置当前slice的poc
int pocCurr = slice->m_poc;//当前poc
int type = newFrame->m_lowres.sliceType;//获取当前帧类型
bool bIsKeyFrame = newFrame->m_lowres.bKeyframe;//当前是否为关键帧
slice->m_nalUnitType = getNalUnitType(pocCurr, bIsKeyFrame);//返回前置图像NAL类型,后置图像NAL类型,关键帧NAL类型(并不是最终类型)
if (slice->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL)//如果是IDR类型,设置最近的一个关键帧位置 (只在openGOP关闭下)
m_lastIDR = pocCurr;
slice->m_lastIDR = m_lastIDR;//设置关键帧位置(所有poc=0都是此类型,所以可以不再if里面)
slice->m_sliceType = IS_X265_TYPE_B(type) ? B_SLICE : (type == X265_TYPE_P) ? P_SLICE : I_SLICE;//确定slice类型
if (type == X265_TYPE_B)//如果是不可参考B帧
{
newFrame->m_encData->m_bHasReferences = false;//没有帧参考它 设为false
// Adjust NAL type for unreferenced B frames (change from _R "referenced"
// to _N "non-referenced" NAL unit type)
switch (slice->m_nalUnitType)
{
case NAL_UNIT_CODED_SLICE_TRAIL_R: //被参考的后置图像,且非TSA、非STSA的视频片段
slice->m_nalUnitType = m_bTemporalSublayer ? NAL_UNIT_CODED_SLICE_TSA_N : NAL_UNIT_CODED_SLICE_TRAIL_N;//设置未被参考
break;
case NAL_UNIT_CODED_SLICE_RADL_R://RADL 前置图像(不依赖IRAP前的帧) 被参考的前置图像  只在openGOP关闭才会有此类型
slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_RADL_N;//设置未被参考
break;
case NAL_UNIT_CODED_SLICE_RASL_R://RASL 前置图像(依赖IRAP前的帧)   被参考的前置图像  只在openGOP打开才会有此类型
slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_RASL_N;//设置未被参考
break;
default:
break;
}
}
else
{
/* m_bHasReferences starts out as true for non-B pictures, and is set to false
* once no more pictures reference it */
newFrame->m_encData->m_bHasReferences = true;//可能有帧参考它设为true
}
m_picList.pushFront(*newFrame);//将帧加入到队列首位置
// Do decoding refresh marking if any
decodingRefreshMarking(pocCurr, slice->m_nalUnitType);//遇到关键帧,设置关键帧前的被参考状态(一般置为false)
computeRPS(pocCurr, slice->isIRAP(), &slice->m_rps, slice->m_sps->maxDecPicBuffering);//slice中rps获取参考帧列表
// Mark pictures in m_piclist as unreferenced if they are not included in RPS
applyReferencePictureSet(&slice->m_rps, pocCurr);//将DPB m_picList列表中在不属于当前帧的参考帧列表的参考状态置为false
slice->m_numRefIdx[0] = X265_MIN(m_maxRefL0, slice->m_rps.numberOfNegativePictures); // 获取L0最大帧数 Ensuring L0 contains just the -ve POC
slice->m_numRefIdx[1] = X265_MIN(m_maxRefL1, slice->m_rps.numberOfPositivePictures); // 获取L1最大帧数
slice->setRefPicList(m_picList);//获取参考帧List 以及 POC
X265_CHECK(slice->m_sliceType != B_SLICE || slice->m_numRefIdx[1], "B slice without L1 references (non-fatal)\n");
if (slice->m_sliceType == B_SLICE)
{
/* TODO: the lookahead should be able to tell which reference picture
* had the least motion residual.  We should be able to use that here to
* select a colocation reference list and index */
slice->m_colFromL0Flag = false;//时域MV预测的collocated块标记位
slice->m_colRefIdx = 0;//时域MV预测的collocated图像的参考索引号
slice->m_bCheckLDC = false;//暂时没发现其用途
}
else
{
slice->m_bCheckLDC = true;//暂时没发现其用途
slice->m_colFromL0Flag = true;//时域MV预测的collocated块标记位
slice->m_colRefIdx = 0;//时域MV预测的collocated图像的参考索引号
}
slice->m_sLFaseFlag = (SLFASE_CONSTANT & (1 << (pocCurr % 31))) > 0;//计算m_sLFaseFlag值
/* Increment reference count of all motion-referenced frames to prevent them
* from being recycled. These counts are decremented at the end of
* compressFrame() */
//将当前帧的参考帧的参考次数都自加一
int numPredDir = slice->isInterP() ? 1 : slice->isInterB() ? 2 : 0;//获取当前有几个list
for (int l = 0; l < numPredDir; l++)
{
for (int ref = 0; ref < slice->m_numRefIdx[l]; ref++)
{
Frame *refpic = slice->m_refPicList[l][ref];
ATOMIC_INC(&refpic->m_countRefEncoders);//原子锁,自加一
}
}
}
/** 函数功能           : slice中rps获取参考帧列表
/*  调用范围           : 只在DPB::prepareEncode函数中被调用
* \参数 curPoc         : 当前帧的POC
* \参数 isRAP          : 是否关键帧
* \参数 rps            : slice中的rps &slice->m_rps
* \参数 maxDecPicBuffer: 解码需要的最大buffer大小
*   返回值             : null
**/
void DPB::computeRPS(int curPoc, bool isRAP, RPS * rps, unsigned int maxDecPicBuffer)
{
unsigned int poci = 0, numNeg = 0, numPos = 0;//poci:计数参考帧, numNeg:计数前向参考帧, numPos:计数后向参考帧;
Frame* iterPic = m_picList.first();
while (iterPic && (poci < maxDecPicBuffer - 1))//在最大buffer内寻求参考帧
{
if ((iterPic->m_poc != curPoc) && iterPic->m_encData->m_bHasReferences)//不是当前帧且是可被参考的帧
{
rps->poc[poci] = iterPic->m_poc;//获取参考帧poc
rps->deltaPOC[poci] = rps->poc[poci] - curPoc;//获取参考帧间的poc差值
(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列表中的deltaPOC和bused 按照 远 近 (当前帧) 近 远的次序排序
}
/* Marking reference pictures when an IDR/CRA is encountered. */
/** 函数功能       : 遇到关键帧,设置关键帧前的被参考状态(一般置为false)
/*  调用范围       : 只在DPB::prepareEncode函数中被调用
* \参数 pocCurr    : 当前帧的POC
* \参数 nalUnitType: 帧类型
*   返回值         : null
**/
void DPB::decodingRefreshMarking(int pocCurr, NalUnitType nalUnitType)
{
if (nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL)//如果当前是IDR 不是CRA
{
/* If the nal_unit_type is IDR, all pictures in the reference picture
* list are marked as "unused for reference" */
Frame* iterFrame = m_picList.first();//获取队列第一帧
while (iterFrame)
{
if (iterFrame->m_poc != pocCurr)
iterFrame->m_encData->m_bHasReferences = false;  //将buffer里面的帧都置为没有帧参考 因为当前IDR帧之后的帧一定不会继续参考前面这些帧了
iterFrame = iterFrame->m_next;
}
}
else // CRA or No DR
{
if (m_bRefreshPending && pocCurr > m_pocCRA)//当前帧已经在CRA帧后面 并且 m_bRefreshPending为true  将CRA前的帧的参考置为false
{
/* If the bRefreshPending flag is true (a deferred decoding refresh
* is pending) and the current temporal reference is greater than
* the temporal reference of the latest CRA picture (pocCRA), mark
* all reference pictures except the latest CRA picture as "unused
* for reference" and set the bRefreshPending flag to false */
Frame* iterFrame = m_picList.first();
while (iterFrame)
{
if (iterFrame->m_poc != pocCurr && iterFrame->m_poc != m_pocCRA)
iterFrame->m_encData->m_bHasReferences = false;  //在CRA帧之后,前置帧将不被参考
iterFrame = iterFrame->m_next;
}
m_bRefreshPending = false;//前置状态置为false
}
if (nalUnitType == NAL_UNIT_CODED_SLICE_CRA)//CRA 关键帧 在openGOP时使用
{
/* If the nal_unit_type is CRA, set the bRefreshPending flag to true
* and pocCRA to the temporal reference of the current picture */
m_bRefreshPending = true; //表示有CRA前置帧
m_pocCRA = pocCurr;//在openGOP打开下 最近的一个关键帧位置
}
}
/* Note that the current picture is already placed in the reference list and
* its marking is not changed.  If the current picture has a nal_ref_idc
* that is not 0, it will remain marked as "used for reference" */
}
/** Function for applying picture marking based on the Reference Picture Set */
/** 函数功能           : 将DPB m_picList列表中在不属于当前帧的参考帧列表的参考状态置为false
/*  调用范围           : 只在DPB::prepareEncode函数中被调用
* \参数 rps            : slice中的rps &slice->m_rps
* \参数 curPoc         : 当前帧的POC
*   返回值             : null
**/
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)
{
// loop through all pictures in the Reference Picture Set
// to see if the picture should be kept as reference picture
bool referenced = false;
for (int i = 0; i < rps->numberOfPositivePictures + rps->numberOfNegativePictures; i++)//将需要参考的置为ture
{
if (iterFrame->m_poc == curPoc + rps->deltaPOC[i])
{
referenced = true;
break;
}
}
if (!referenced)
iterFrame->m_encData->m_bHasReferences = false;//不在上述列表中的 ,其参考位置为false
}
iterFrame = iterFrame->m_next;
}
}
/* deciding the nal_unit_type */
/** 函数功能       : 返回前置图像NAL类型,后置图像NAL类型,关键帧NAL类型(并不是最终类型)
/*  调用范围       : 只在DPB::prepareEncode函数中被调用
* \参数 curPOC     : 当前poc
* \参数 bIsKeyFrame: 是否为IDR帧
*   返回值         : 返回前置图像NAL类型,后置图像NAL类型,关键帧NAL类型
**/
NalUnitType DPB::getNalUnitType(int curPOC, bool bIsKeyFrame)
{
if (!curPOC)
return NAL_UNIT_CODED_SLICE_IDR_W_RADL;//视频序列第一帧, IDR帧,前置帧无参考前面的帧
if (bIsKeyFrame)//当前为关键帧
return m_bOpenGOP ? NAL_UNIT_CODED_SLICE_CRA : NAL_UNIT_CODED_SLICE_IDR_W_RADL;//如果打开GOP , 则当前的关键帧为CRA(其前置图像可以为RASL可以参考前面的帧)
if (m_pocCRA && curPOC < m_pocCRA)
// All leading pictures are being marked as TFD pictures here since
// current encoder uses all reference pictures while encoding leading
// pictures. An encoder can ensure that a leading picture can be still
// decodable when random accessing to a CRA/CRANT/BLA/BLANT picture by
// controlling the reference pictures used for encoding that leading
// picture. Such a leading picture need not be marked as a TFD picture.
return NAL_UNIT_CODED_SLICE_RASL_R;//只在打开openGOP情况下进入:如果当前帧号小于最近的关键帧,返回前置图像为RASL_R(被参考的前置图像,并且前置图像也参考其前面的帧)
if (m_lastIDR && curPOC < m_lastIDR)
return NAL_UNIT_CODED_SLICE_RADL_R;//只在关闭openGOP情况下进入:如果当前帧号小于最近的关键帧,返回前置图像为RADL_R(被参考的前置图像,并且前置图像不参考其前面的帧)
return NAL_UNIT_CODED_SLICE_TRAIL_R;//被参考的后置图像,且非TSA、非STSA的视频片段
}

x265-1.8版本-encoder/dpb.cpp注释相关推荐

  1. x265-1.7版本-encoder/dpb.cpp注释

    注:问号以及未注释部分 会在x265-1.8版本内更新 /*********************************************************************** ...

  2. x265-1.7版本-encoder/slicetype.cpp注释

    注:问号以及未注释部分 会在x265-1.8版本内更新 /*********************************************************************** ...

  3. x265-1.8版本-encoder/slicetype.cpp注释

    注:问号以及未注释部分 会在x265-1.9版本内更新 /*********************************************************************** ...

  4. x265-1.8版本-encoder/frameencoder.cpp注释

    注:问号以及未注释部分 会在x265-1.9版本内更新 /*********************************************************************** ...

  5. x265-1.7版本-encoder/frameencoder.cpp注释

    注:问号以及未注释部分 会在x265-1.8版本内更新 /*********************************************************************** ...

  6. x265-1.8版本-encoder/ratecontrol.cpp注释

    注:问号以及未注释部分 会在x265-1.9版本内更新 /*********************************************************************** ...

  7. x265-1.8版本-encoder/motion.cpp注释

    注:问号以及未注释部分 会在x265-1.9版本内更新 /*********************************************************************** ...

  8. x265-1.7版本-encoder/motion.cpp注释

    注:问号以及未注释部分 会在x265-1.8版本内更新 /*********************************************************************** ...

  9. x265-1.8版本-encoder/frameencoder.h注释

    注:问号以及未注释部分 会在x265-1.9版本内更新 /*********************************************************************** ...

最新文章

  1. shell   %% , ##,#,% 用法
  2. Ubuntu apt-get 源详解
  3. mysql用户权限表join_MyBatis映射利用mysql left join 解决N+1查询问题
  4. 吴裕雄--天生自然 高等数学学习:平面及其方程
  5. 设计模式之行为型备忘录模式
  6. php函数默认参数放在哪测,php函数默认参数的实例代码
  7. linux bash脚本 坑,向大家分享一个shell脚本的坑
  8. 2018美赛C题翻译加原文
  9. java实现签名和解签
  10. 教育技术资源大全(05-11-28)
  11. 泰坦尼克 (有剧透)
  12. 一个有趣的字符滚动GIF动态验证码识别
  13. 在国企的日子(第三章中部 出差)
  14. 卷积神经网络(CNN)的参数优化方法
  15. 大吉大利,今晚吃鸡!
  16. 安卓9.0设置WIFI静态IP地址。
  17. 将Firefox浏览器的界面语言设置为英文
  18. perform指标分析_如何看待Perform3D和Abaqus在结构分析中的作用
  19. 计算机按照原理分为哪几种,计算机按原理可分为哪三大类
  20. Execution failed for task ':app:mergeDebugResources'

热门文章

  1. 水仙花数python代码多种方式_水仙花数的三种解决方法(Python实现)
  2. java 公式计算_java 实现的公式计算
  3. 安卓苹果手机有效清除微信浏览器内部缓存
  4. 剑指 offer 面试题精选图解 10-I.斐波那契数列
  5. U盘用作启动盘后空间变为原来的一半
  6. 优秀开源音乐项目---落雪音乐软件(免费听歌下载歌曲)
  7. 一般怎样恢复u盘丢失的文件
  8. 算法:一个长字符串中含多个连续和不连续的空格,求不含空格的最长字符串长度
  9. 虚拟机介绍与使用(VMware Workstation)
  10. 阿里,京东,蚂蚁面试题