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. input常用属性

    对于input的使用,大家都很熟悉的,<input> 标签用于搜集用户信息.根据不同的 type 属性值,输入字段拥有很多种形式.输入字段可以是文本字段.复选框.掩码后的文本控件.单选按钮 ...

  2. Eclipse+Tomcat搭建https环境

    一.首先在本地建立一个keystore文件 用命令:keytool -v -genkey -alias tomcat -keyalg RSA -keystore c:/tomcat.keystore ...

  3. nodejs-2:模块与包管理工具

    多人协作时,大量的js文件批量的引入到页面中,会出现变量被覆 盖掉方法被重写掉的情况,特别是存在一些依赖关系的时候,还容 易导致页面出错,这是因为js天生就缺少一种模块的管理机制来 隔离实现功能的js ...

  4. Geolocation API 原理及方法

    使用IP地址:基于Web的数据库:无线网络连接定位:三角测量:GPS技术:来测量经度和纬度.(综合了所有技术)地理定位的精确度,有很多方法可以定位用户的地理位置,并且每种方法都有不同的精度.桌面浏览器 ...

  5. HackerRank-Longest Subarray

    give an array and target value, find the max length of the subarray which sum of the elements is les ...

  6. FreeBSD 无线配置

    无线配置在 handbook 中早已有了,但 handbook 中采用写入配置文件的办法,缺乏灵活性,补充下 on the fly 的方法 假设网卡接口为 ath0 ifconfig wlan0 cr ...

  7. cps变换

    网上看了很多内容,很少有给出一个准确的概念,它的英文全称是continuous passing style, 直译为连续传递样式,那么cps transform就是将一些原本不是continuous ...

  8. linux 持续构建(自动部署) 重启动tomcat或进程的脚本

    #!/bin/sh TOMCAT_PATH=`dirname "$0"` echo "TOMCAT_PATH is /usr/local/tomcat" PID ...

  9. C#实现任意大数的计算和简单逻辑命题的证明——前言

    介绍 这是本人毕业设计的项目,一直想将其整理成文,可一不小心4年就过去了(这个时间又可以读个大学了).现在给自己定一个目标,一个月时间里将项目的所有关键点都整理出来.不然真怕一眨眼又一个4年过去了,而 ...

  10. switch

    关于java中switch使用的一些说明 switch(表达式) { case常量表达式1:语句1; .... case常量表达式2:语句2; default:语句; } default就是如果没有符 ...