前面已经通过cavlc解析出了numCoeff、trailingOnes、trailingSigns(拖尾系数符号)、levels、totalZeros、runBefore等值,在反变换量化之前,需要根据这些值还原系数矩阵

一、定义

定义数据保存矩阵:int m_residual_matrix_luma[16][4][4];
定义还原函数:Restore_coeff_matrix

二、知识储备

一个宏块在进行CAVLC编码时是如何划分的:4 * 4模式是如何划分的呢?首先将16 * 16的宏块划分成4个8 * 8的,每个8 * 8的都是由cbp的一个bit表示的

基本编程思路:cavlc结果->还原为8 * 8的矩阵->4 * 4的矩阵->再填充矩阵数组

三、代码实现

1、重建8 * 8系数矩阵框架:

//<变换量化><1>根据cavlc结果还原系数矩阵
void CResidual::Restore_coeff_matrix()
{UINT8 cbp_luma = m_macroblock_belongs->m_cbp_luma;UINT8 cbp_chroma = m_macroblock_belongs->m_cbp_chroma;//<变换量化><1>4*4宏块if (m_macroblock_belongs->m_mb_type == I4MB){for (int blk8Idx = 0; blk8Idx < 4; blk8Idx++){if (cbp_luma & (1 << blk8Idx))     //<变换量化><1>判断是否有系数矩阵{restore_8x8_coeff_block_luma(m_coeff_matrix_luma, blk8Idx, LUMA);      //<变换量化><1>处理8*8的块,将里面4个4*4的系数矩阵都解析出来}}}
}

2、解析8 * 8矩阵

//<变换量化><1>重建8 * 8系数矩阵接口
void CResidual::restore_8x8_coeff_block_luma(int (*matrix)[4][4], int idx, int blockType)
{int blkColumnIdxStart = 2 * (idx / 2),  blkRowIdxStart = 2 * (idx % 2);      //<变换量化><2>计算宏块索引序号,宏块的计数是针对于整体16 * 16的块而言的,第一行0-3,第二行4-7for (int columnIdx = blkColumnIdxStart; columnIdx < blkColumnIdxStart + 2; columnIdx ++){for (int rowIdx = blkRowIdxStart; rowIdx < blkRowIdxStart + 2; rowIdx++){restore_4x4_coeff_block_luma(columnIdx, rowIdx, blockType);}}
}

3、解析4 * 4矩阵

void CResidual::restore_4x4_coeff_block_luma(int column_idx, int row_idx, int blockType)
{int max_coeff_num = 0, start_idx = 0;Coeff4x4Block *targetBlock = NULL;switch (blockType){case LUMA:max_coeff_num = 16;targetBlock = &luma_residual[column_idx][row_idx];     //<变换量化><2>前面cavlc解析出的结果break;case LUMA_INTRA16x16AC:start_idx = 1;        //<变换量化><2>设置为1是因为直流分量已经被单独解析了,所以这里需要从1开始max_coeff_num = 15;targetBlock = &luma_residual16x16_AC[column_idx][row_idx];break;default:break;}int coeffBuf[16] = { 0 };UINT8 numCoeff = targetBlock->numCoeff, coeffIdx = numCoeff;UINT8 trailingOnes = targetBlock->trailingOnes, trailingLeft = trailingOnes;UINT8 totalZeros = targetBlock->totalZeros;// write trailing ones//<变换量化><2>[10 0 2 3 0 0 5 3 0 1....]//<变换量化><2>[10 2 3 5 3 1]   先写为这种,后面再补0for (int i = numCoeff - trailingOnes, j = trailingOnes - 1; j >= 0; j--){coeffBuf[i++] = targetBlock->trailingSign[j];}// write levels//<变换量化><2>写非零非拖尾系数的值for (int i = numCoeff - trailingOnes - 1; i >= 0; i--){coeffBuf[i] = targetBlock->levels[numCoeff - trailingOnes - 1 - i];}// move levels with run_before//<变换量化><2>[10 0 2 3 0 0 5 3 0 1....]//<变换量化><2>[10 2 3 5 3 1 0 0 0 0]     totalZeros=4  - runBefore=1//<变换量化><2>[10 2 3 5 3 0 0 0 0 1]      totalZeros=3  - runBefore=0//<变换量化><2>[10 2 3 5 0 0 0 3 0 1]      totalZeros=3  - runBefore=2//<变换量化><2>[10 2 3 0 0 0 5 3 0 1]for (int i = numCoeff - 1; i > 0; i--){swap(coeffBuf[i], coeffBuf[i + totalZeros]);totalZeros -= targetBlock->runBefore[i];}swap(coeffBuf[0], coeffBuf[totalZeros]); //<变换量化><2>如果totalZeros还不为0,需要交换最低频前面的0insert_matrix(m_coeff_matrix_luma, coeffBuf, start_idx, max_coeff_num, column_idx, row_idx);      //<变换量化><2>插入系数矩阵数组//   int blkIdx = position_to_block_index(row_idx, column_idx);
//  coeff_invers_transform(m_coeff_matrix_luma[blkIdx], m_residual_matrix_luma[blkIdx]);
}

4、填充系数矩阵数组:

注意因为是Z字型扫描,所以我们定义了一个坐标数组

【H264解析Demo】10、变换量化_1_CAVLC结果还原为系数矩阵相关推荐

  1. 【H264解析Demo】10、变换量化_3_反变换

    代码实现 //<变换量化><4>反变换(参数1:保存反量化系数 参数2:保存反变换之后) void CResidual::coeff_invers_transform(int( ...

  2. python经典书籍推荐-推荐10本量化Python书单,好好学习天天向上

    推荐10本量化Python书~Python非常灵活,让实验变得容易.解决简单问题的方法简单而优雅.Python为新手程序员提供了一个很好的实验室. Python具有一些特征,使其成为第一种编程语言的接 ...

  3. 自己做量化交易软件(10)通通量化AI框架的数据获取与格式

    自己做量化交易软件(10)通通量化AI框架的数据获取与格式 我与2018年07月08日开始学习python编程和设计通通量化AI框架,到昨天晚上2018年10月30日,基本框架已经完成.能够显示K线图 ...

  4. HM编码器代码阅读(32)——帧间预测之AMVP/Merge模式(七)encodeResAndCalcRdInterCU函数:残差计算、变换量化

    encodeResAndCalcRdInterCU 原理和细节 经过运动估计.运动补偿,我们得到了MV以及参考块,那么接下来是计算残差.计算MVD,然后对系数进行变换.量化. encodeResAnd ...

  5. HM编码器代码阅读(20)——与变换量化有关的其他知识

    与变换量化有关的其他知识 变换 哈达玛变换 哈达玛变换是广义傅立叶变换的一种,它的变换矩阵Hm是一个2^m x 2^m的矩阵. 哈达玛变换及其矩阵有下面的几个特性: 1.hadamard矩阵元素都是正 ...

  6. PHP二维码解析demo

    @TOPHP二维码解析demoC PHP二维码解析demo PHP二维码解析demo

  7. 【一起学习输入法】华宇拼音输入法开源版本解析(10)

    [一起学习输入法]华宇拼音输入法开源版本解析(10)           原创:good02xaut(CSDN) 硬件框图

  8. wireshark添加h264解析插件

    1.下载h264解析插件rtp_h264_extractor.lua https://github.com/volvet/h264extractor 2.将插件rtp_h264_extractor.l ...

  9. 深度学习与计算机视觉教程(10) | 轻量化CNN架构 (SqueezeNet,ShuffleNet,MobileNet等)(CV通关指南·完结)

    作者:韩信子@ShowMeAI 教程地址:https://www.showmeai.tech/tutorials/37 本文地址:https://www.showmeai.tech/article-d ...

最新文章

  1. Linux IPv6 地址配置
  2. python图像直方图与直方图均衡化
  3. IDE安装Lombok插件提高开发效率
  4. JavaScript---事件详解
  5. java 代码执行el,专属于java的漏洞——EL表达式注入
  6. 传智杯Java终端有一天您厌烦了电脑上又丑又没用的终端,打算自己实现一个 Terminal
  7. java=====Striing date 转化
  8. 野火IMJAVA开发的即时通讯系统源码
  9. Zcash已发布ZIP 313提案
  10. apply_async进程不执行_[粉丝问答6]子进程进程的父进程关系
  11. 00002-微信小游戏--触摸事件
  12. 2/8法则系列 | 你真的了解二八法则吗?
  13. 解决国内手机安装Google Play打开闪退问题
  14. LUN详解 iscsi
  15. 微信公众号自动回复多图文(php)
  16. GEA 1.6 运行时引擎架构
  17. linux 服务器端listen(5)
  18. SOLIDWORKS的钛合金分析
  19. Android 悬浮窗权限各机型各系统适配大全
  20. 质量基础设施一站式公共服务平台建设,NQI系统开发

热门文章

  1. 达内python培训课程
  2. Web笔记(二)Tomcat 使用总结
  3. Revit API 开发(12): Revit 文件存储结构
  4. css预处理器sass/scss入门
  5. 海尔系列报道之一:海尔“小微”怎么玩
  6. 苹果体验店:鲜为人知的乔布斯的秘密
  7. 运行的程序总是莫名被 Killed
  8. 教你win10电脑声音太小怎么办
  9. linux 通过lvm合并磁盘
  10. 网上购车平台其实也可以这样上私户