HEVC帧内预测的35中预测模式是在PU基础上定义的,实际帧内预测的过程则以TU为单位。PU以四叉树划分TU,一个PU内所有TU共享同一种预测模式。帧内预测分3个步骤:

(1) 判断当前TU相邻像素点是否可用并做相应的处理

(2) 对参考像素进行滤波

(3) 根据滤波后的参考像素计算当前TU的预测像素值。

HM-16.7中fillReferenceSamples()主要实现第一个步骤,真正进行帧内预测之前,使用重建后的Yuv图像对当前PU的相邻样点进行赋值,为接下来进行的角度预测提供参考样点值,对应于draft 8.4.4.2.2的内容。主要过程是:

(1)如果所有相邻点均不可用,则参考样点值均被赋值为DC值;

iDCValue = 1 << (bitDepth - 1),对于8bit像素,该值为128。

(2)如果所有相邻点均可用,则参考样点值都会被赋值为重建Yuv图像中与其位置相同的样点值;

(3)如果不满足上述两个条件,则按照从左下往左上,从左上往右上的扫描顺序进行遍历,如果第一个点不可用,则使用下一个可用点对应的重建Yuv样点值对其进行赋值;对于除第一个点外的其它邻点,如果该点不可用,则使用它的前一个样点值进行赋值(前一个步骤保证了前一个样点值一定是存在的),直到遍历完毕。

 Void fillReferenceSamples( const Int bitDepth,
#if O0043_BEST_EFFORT_DECODING
const Int bitDepthDelta,
#endif
const Pel* piRoiOrigin,
Pel* piIntraTemp,
const Bool* bNeighborFlags,
const Int iNumIntraNeighbor,
const Int unitWidth,
const Int unitHeight,
const Int iAboveUnits,
const Int iLeftUnits,
const UInt uiWidth,
const UInt uiHeight,
const Int iPicStride )
{
const Pel* piRoiTemp;//piRoiOrgin指向重建Yuv图像对应于当前PU所在位置的首地址,piRoiTemp用于指向所感兴趣的重建Yuv的位置
Int i, j;
Int iDCValue = << (bitDepth - );//参考像素不可用时的填充值,8bit时候为128.
const Int iTotalUnits = iAboveUnits + iLeftUnits + ; //+1 for top-left //以4个像素点为单位标记,其中左上角单独标记 if (iNumIntraNeighbor == ) // all samples are not available
{
// Fill border with DC value
for (i=; i<uiWidth; i++) //!< AboveLeft + Above + AboveRight
{
piIntraTemp[i] = iDCValue;
}
for (i=; i<uiHeight; i++)//!< Left + BelowLeft
{
piIntraTemp[i*uiWidth] = iDCValue;
}
}
else if (iNumIntraNeighbor == iTotalUnits)// all samples are available
{
// Fill top-left border and top and top right with rec. samples
piRoiTemp = piRoiOrigin - iPicStride - ; //!< AboveLeft for (i=; i<uiWidth; i++)
{
#if O0043_BEST_EFFORT_DECODING
piIntraTemp[i] = piRoiTemp[i] << bitDepthDelta;
#else
piIntraTemp[i] = piRoiTemp[i];
#endif
} // Fill left and below left border with rec. samples
piRoiTemp = piRoiOrigin - ; for (i=; i<uiHeight; i++)
{
#if O0043_BEST_EFFORT_DECODING
piIntraTemp[i*uiWidth] = (*(piRoiTemp)) << bitDepthDelta;
#else
piIntraTemp[i*uiWidth] = *(piRoiTemp);//!< 每个参考样点赋值为对应位置重建Yuv样点值
#endif
piRoiTemp += iPicStride;//!< 指向重建Yuv下一行
}
}
else // reference samples are partially available
{
// all above units have "unitWidth" samples each, all left/below-left units have "unitHeight" samples each
//!< neighboring samples的总数
const Int iTotalSamples = (iLeftUnits * unitHeight) + ((iAboveUnits + ) * unitWidth);
Pel piIntraLine[ * MAX_CU_SIZE];
Pel *piIntraLineTemp;//!<临时存储用于填充neighboring samples的样点值
const Bool *pbNeighborFlags;//保存以四个像素点为单位的可用性 // Initialize
for (i=; i<iTotalSamples; i++)
{
piIntraLine[i] = iDCValue;
} // Fill top-left sample
piRoiTemp = piRoiOrigin - iPicStride - ;//!< 指向重建Yuv左上角
piIntraLineTemp = piIntraLine + (iLeftUnits * unitHeight);//!< piAdiLine的扫描顺序为左下到左上,再从左到右上
pbNeighborFlags = bNeighborFlags + iLeftUnits;//!< 标记neighbor可用性的数组同样移动至左上角
if (*pbNeighborFlags)//!< 如果左上角可用,则左上角4个像素点均赋值为重建Yuv左上角的样点值
{
#if O0043_BEST_EFFORT_DECODING
Pel topLeftVal=piRoiTemp[] << bitDepthDelta;
#else
Pel topLeftVal=piRoiTemp[];
#endif
for (i=; i<unitWidth; i++)
{
piIntraLineTemp[i] = topLeftVal;
}
} // Fill left & below-left samples (downwards)
piRoiTemp += iPicStride;//!< piRoiTemp指向重建Yuv的左边界
piIntraLineTemp--;//移动指针至左边界
pbNeighborFlags--;//移动指针至左边界 for (j=; j<iLeftUnits; j++)//从左向左下扫描
{
if (*pbNeighborFlags)//如果可用
{
for (i=; i<unitHeight; i++)//!< 每个4x4块里的4个样点分别被赋值为对应位置的重建Yuv的样点值 
{
#if O0043_BEST_EFFORT_DECODING
piIntraLineTemp[-i] = piRoiTemp[i*iPicStride] << bitDepthDelta;
#else
piIntraLineTemp[-i] = piRoiTemp[i*iPicStride];
#endif
}
}
piRoiTemp += unitHeight*iPicStride;//!< 指针挪到下一个行(以4x4块为单位,即实际上下移了4行) 
piIntraLineTemp -= unitHeight;//!< 指针下移  
pbNeighborFlags--;//!< 指针下移  
} // Fill above & above-right samples (left-to-right) (each unit has "unitWidth" samples)
piRoiTemp = piRoiOrigin - iPicStride;//!< piRoiTemp 指向重建Yuv的上边界
// offset line buffer by iNumUints2*unitHeight (for left/below-left) + unitWidth (for above-left)
piIntraLineTemp = piIntraLine + (iLeftUnits * unitHeight) + unitWidth;
pbNeighborFlags = bNeighborFlags + iLeftUnits + ;
for (j=; j<iAboveUnits; j++) //!< 从左扫描至右上
{
if (*pbNeighborFlags)//如果可用
{
for (i=; i<unitWidth; i++)//!< 每个4x4块里的4个样点分别被赋值为对应位置的重建Yuv的样点值  
{
#if O0043_BEST_EFFORT_DECODING
piIntraLineTemp[i] = piRoiTemp[i] << bitDepthDelta;
#else
piIntraLineTemp[i] = piRoiTemp[i];
#endif
}
}
piRoiTemp += unitWidth;//!< 指针右移,实际是右移了4
piIntraLineTemp += unitWidth;//!< 指针右移,实际是右移了4
pbNeighborFlags++;//!< 指针右移,以4个像素点为单位标记可用性
} // Pad reference samples when necessary
Int iCurrJnit = ;
Pel *piIntraLineCur = piIntraLine;//!< 指向左下角(纵坐标最大的那个位置,即扫描起点)
const UInt piIntraLineTopRowOffset = iLeftUnits * (unitHeight - unitWidth); if (!bNeighborFlags[])
{
// very bottom unit of bottom-left; at least one unit will be valid.
{
Int iNext = ;
while (iNext < iTotalUnits && !bNeighborFlags[iNext])
{
iNext++;
}
Pel *piIntraLineNext = piIntraLine + ((iNext < iLeftUnits) ? (iNext * unitHeight) : (piIntraLineTopRowOffset + (iNext * unitWidth)));
const Pel refSample = *piIntraLineNext;
// Pad unavailable samples with new value
Int iNextOrTop = std::min<Int>(iNext, iLeftUnits);
// fill left column
while (iCurrJnit < iNextOrTop) //!< 遍历所有neighboring samples
{
for (i=; i<unitHeight; i++)
{
piIntraLineCur[i] = refSample;
}
piIntraLineCur += unitHeight;
iCurrJnit++;
}
// fill top row
while (iCurrJnit < iNext)
{
for (i=; i<unitWidth; i++)
{
piIntraLineCur[i] = refSample;
}
piIntraLineCur += unitWidth;
iCurrJnit++;
}
}
} // pad all other reference samples.
while (iCurrJnit < iTotalUnits)
{
if (!bNeighborFlags[iCurrJnit]) // samples not available
{
{
const Int numSamplesInCurrUnit = (iCurrJnit >= iLeftUnits) ? unitWidth : unitHeight;
const Pel refSample = *(piIntraLineCur-);
for (i=; i<numSamplesInCurrUnit; i++)
{
piIntraLineCur[i] = refSample;
}
piIntraLineCur += numSamplesInCurrUnit;
iCurrJnit++;
}
}
else
{
piIntraLineCur += (iCurrJnit >= iLeftUnits) ? unitWidth : unitHeight;
iCurrJnit++;
}
} // Copy processed samples piIntraLineTemp = piIntraLine + uiHeight + unitWidth - ;
// top left, top and top right samples
for (i=; i<uiWidth; i++)
{
piIntraTemp[i] = piIntraLineTemp[i];
} piIntraLineTemp = piIntraLine + uiHeight - ;
for (i=; i<uiHeight; i++)
{
piIntraTemp[i*uiWidth] = piIntraLineTemp[-i];
}
}
}

【HEVC】2、HM-16.7编码一个CU(帧内部分) 1.帧内预测相邻参考像素获取的更多相关文章

  1. 【HEVC】4、HM-16.7编码一个CU(帧内部分) 3.帧内预测各种模式实现

    HEVC中一共定义了35中帧内编码预测模式,编号分别以0-34定义.其中模式0定义为平面模式(INTRA_PLANAR),模式1定义为均值模式(INTRA_DC),模式2~34定义为角度预测模式(IN ...

  2. HM中字典编码分析

    LZ77算法基本过程 http://jpkc.zust.edu.cn/2007/dmt/course/MMT03_05_2.htm LZ77压缩算法详解 http://wenku.baidu.com/ ...

  3. JSON C# Class Generator是一个从JSON文本中生成C#内的应用程序

    JSON C# Class Generator是一个从JSON文本中生成C#内的应用程序 .NET平台开源项目速览(18)C#平台JSON实体类生成器JSON C# Class Generator   ...

  4. 判断一个IP地址是否是本局域网内地址

    //        /// <summary>        /// 判断一个IP地址是否是本局域网内地址,是返回true 否则返回false,        /// </summa ...

  5. TensorFlow-Bitcoin-Robot:一个基于 TensorFlow LSTM 模型的 Bitcoin 价格预测机器人

    简介 TensorFlow-Bitcoin-Robot:一个基于 TensorFlow LSTM 模型的 Bitcoin 价格预测机器人. 文章包括一下几个部分: 1.为什么要尝试做这个项目? 2.为 ...

  6. TensorFlow-Bitcoin-Robot:一个基于 TensorFlow LSTM 模型的 Bitcoin 价格预测机器人。

    简介 TensorFlow-Bitcoin-Robot:一个基于 TensorFlow LSTM 模型的 Bitcoin 价格预测机器人. 文章包括一下几个部分: 1.为什么要尝试做这个项目? 2.为 ...

  7. 【python系统学习16】编码基础知识

    编码 计算机是怎么传输和存储数据的? 就是把人类认识的中英文字.其他国家语言.数字甚至运算符等符号转成二进制的0.1,并进行存储和传输. 编码 人类语言:中英文字.其他国家语言.数字甚至运算符等符号 ...

  8. CI Weekly #16 | 从另一个角度看开发效率:flow.ci 数据统计功能上线

    很开心的告诉大家,flow.ci 数据统计功能已正式上线. 进入 flow.ci 控制台,点击「数据分析」按钮,你可以按照时间日期筛选,flow.ci 将多维度地展示「组织与项目」的构建数据指标与模型 ...

  9. 13.14.15.16.17&《一个程序猿的生命周期》读后感

    13.TDS 的标准是什么,怎么样才能认为他是一个标准的TDS?? 14.软件的质量包括哪些方面,如何权衡软件的质量? 15.如何解决功能与时间的矛盾,优秀的软件团队会发布有已知缺陷的软件么? 16. ...

随机推荐

  1. node.js Websocket实现扫码二维码登录---GoEasy

    最近在做一个扫码登录功能,为此我还在网上搜了一下关于微信的扫描登录的实现方式.当这个功能完成了后,我决定将整个实现思路整理出来,方便自己以后查看也方便其他有类似需求的程序猿些. 要实现扫码登录我们需要 ...

  2. CSS counter-reset 属性

    一.实例 对部分和子部分进行编号(比如 "Section 1"."1.1"."1.2")的方法: eg: css部分: ol { list- ...

  3. CSS中的display属性

    CSS中的display属性 display:block是可以把非块级元素强制转换为块级元素显示,如内嵌元素span,原来不支持设置宽高,宽度是由内容撑开的,几个span元素是在同一行内的,如果给sp ...

  4. Java JDBC使用方法

    public class JDBC{public static void main(String[] args){//查询数据selectData();}//查询数据的方法private static ...

  5. JavaScript中reduce()方法

    原文  http://aotu.io/notes/2016/04/15/2016-04-14-js-reduce/   JavaScript中reduce()方法不完全指南 reduce() 方法接收 ...

  6. MyBatis学习(一)

    前言 再过一个月,转行做java web就满一年了.当初吸引我进入公司的,其实并不是java web,而是领导给我描述的hadoop生态圈.公司的hadoop集群以及大数据业务.可是进入公司后才发现, ...

  7. WebAPI学习点滴(二)

    刚开始学习WebApi就遇到了问题,在同一个API控制器中,如果两个方法的签名相同,比如 [HttpGet] public string GetString() { return "Hell ...

  8. 4G基站如何查询

     例如:4600125086016801代码断码如下断:46001(营运商代码) 2508(十进位制9480,CGI代码,CGI相当于是4G的LAC) 6016801(十进位制100755457,eN ...

  9. JQuery实现列表中复选框全选反选功能封装

    我们在做列表的时候经常会遇到全选,反选进行批量处理问题,例如: 我当时就是简单的实现了,然后想封装到公共的js中,封装的太烂,不好意思贴出来了(就是把实现代码之间放到公共js中,然后每个页面都用固定的 ...

  10. Centos6.5 设置Tomcat8 service服务实现自启动和服务管理

    Centos6.5 设置Tomcat8 service服务实现自启动和服务管理 将tomcat设置成像apache,nginx一样. 用serviec xxxx start/stop/restart ...