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. Rxjava的基本使用

    gradle配置: compile 'io.reactivex:rxjava:1.0.9' 观察者: Observer<String> observer = new Observer< ...

  2. 杭电acm 1002 大数模板(一)

    从杭电第一题开始A,发现做到1002就不会了,经过几天时间终于A出来了,顺便整理了一下关于大数的东西 其实这是刘汝佳老师在<算法竞赛 经典入门 第二版> 中所讲的模板,代码原封不动写上的, ...

  3. 开启Java博客

    已经转Java大半年了,Java知识都来自于工作,没有一个系统的学习,所以这一个多月我都在看Java的一些基本东西,准备系统性的学习下Java知识.这一个多月看的也挺多,从servlet,jsp,st ...

  4. Hammer.js--转载自李林峰的园子

    一.前言 移动端框架当前还处在初级阶段,但相对于移动端的应用来说已经有很长时间了.虽然暂时还没有PC端开发的需求量大,但移动端的Web必然是一种趋势,在接触移动端脚本的过程中,最开始想到的是juqer ...

  5. 好的bootstrap文章

    http://www.cnblogs.com/gamehiboy/p/5176618.html http://www.cnblogs.com/landeanfen/p/5821192.html htt ...

  6. 【转】怎么让VS2015编写的程序在XP中顺利运行

    1. 概述 默认配置下VS2015编写的应用程序只能在Win8/Win10上运行.但幸好还保留了生成XP程序的设置项.XP和Win2003的用户还是大量存在的,我们程序软件的发布不能不考虑他们.另外X ...

  7. Python Iterable Iterator Yield

    可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list / tuple / dict / set / str /等(对于这类iterable的对象,因为你可以按照你的意愿进行重 ...

  8. 富文本编辑器防止xss注入javascript版

    富文本编辑器:ueditor 其实富文本编辑器已经有防止xss注入功能,但是你服务端程序在接收的时候在做一次转义,否则有可能然后前端验证直接提交数据导致被xss攻击. 为了节省后端程序开销则在前端 显 ...

  9. [转]''\\=DevExpress 中 汉化包 汉化方法

    [DevExpress]DevExpress 中 汉化包 汉化方法 2016-02-17 21:13 1781人阅读 评论(0) 收藏 举报  分类: DevExpress(24)  版权声明:本文为 ...

  10. PHP eof的使用

    PHP eof的使用 也就是heredoc技术,来部分实现界面与代码的分离 <?php $name = '张三'; print <<<EOT <html> < ...