设为首页 加入收藏

TOP

14.2.3 DM642下XviD CODEC优化(1)
2013-10-07 00:41:48 来源: 作者: 【 】 浏览:68
Tags:14.2.3 DM642 XviD CODEC 优化

14.2.3  DM642下XviD CODEC优化(1)

第13章曾介绍过DM642实现视频编/解码技术的基本过程。C语言实现算法系统框架,线性汇编优化核心函数使模块尽可能软件流水,对于图像数据使用DMA双缓冲的方法,在L2的SRAM内存区开辟图像工作空间,后台开启DMA传输,配置L2 Cache,增加CPU存取数据的命中率。使用CCS开发软件的优化工具,优化组合编译开关,辅助开发人员进行算法优化。

表14-1所示的 XviD MPEG-4视频CODEC底层模块都需要汇编优化,或者Intrinsic指令优化。TI的图像算法库img64x.lib提供了图像处理的常用算法函数,有C语言、线性汇编语言和并行汇编的源代码。一方面开发人员可以直接使用这些库函数,另一方面参考、模仿其汇编优化过程和编程(www.cppentry.com)思路,对自己算法逐步深入汇编优化,如图像变换DCT,库img64x.lib就提供了并行度极高、完全建立了软件流水的函数IMG_fdct_8x8(),运动估计ME中判断块最佳匹配的SAD值函数IMG_sad_16x16()、IMG_sad_8x8()。在使用该库的时候,需特别注意输入源数据、输出结果的格式。如DCT中,输出的结果是每个元素左移了4位;计算SAD时,注意两个图像块边界是否和地址对齐,为了提高并行度尽可能使用对齐的数据存取指令。

下面对编/解码中的运动补偿MC模块作DM642优化。运动补偿的原理是根据运动向量MV的值,对当前宏块补偿出新的宏块,补偿的方式根据像素的精度有1/2、1/4、1/8之分。现在对1/2精度的函数作优化,其他精度的补偿优化读者可通过参考此例来实现。

1.水平方向插值补偿

水平方向插值的原理是图像块的第0列、第1列的元素对应取平均,结果放置在新块的第0列,图像块的第1列、第2列的元素对应取平均,结果放置新块的第1列,依次类推,直到处理完整个图像块。新块即为水平插值补偿块,C语言代码如下。

void interpolate8x8_halfpel_h(uint8_t* const dst,const uint8_t* const src, 
const uint32_t stride, const uint32_t rounding)
{
uint32_t j;          
int r = 1 - rounding;     /*舍尾方式*/
for (j = 0; j < 8*stride; j+=stride){                             // 每次循环处理一列
dst[j + 0] = (uint8_t)((src[j + 0] + src[j + 1] + r )>>1);  //0元素和1元素取平均
dst[j + 1] = (uint8_t)((src[j + 1] + src[j + 2] + r )>>1);  //1元素和2元素取平均
dst[j + 2] = (uint8_t)((src[j + 2] + src[j + 3] + r )>>1);  //2元素和3元素取平均
dst[j + 3] = (uint8_t)((src[j + 3] + src[j + 4] + r )>>1);  //3元素和4元素取平均
dst[j + 4] = (uint8_t)((src[j + 4] + src[j + 5] + r )>>1);  //4元素和5元素取平均
dst[j + 5] = (uint8_t)((src[j + 5] + src[j + 6] + r )>>1);  //5元素和6元素取平均
dst[j + 6] = (uint8_t)((src[j + 6] + src[j + 7] + r )>>1);  //6元素和7元素取平均
dst[j + 7] = (uint8_t)((src[j + 7] + src[j + 8] + r )>>1);  //7元素和8元素取平均
}
}
此函数处理数据规整,源和目标存储区没有依赖性。源和目标地址均为图像空间,源地址不对齐,目标地址对齐。线性汇编优化如下。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   interpolate8x8_halfpel_h_asm_dm642                 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.sect ".text:_interpolate8x8_halfpel_h_asm_dm642"
.global _interpolate8x8_halfpel_h_asm_dm642
_interpolate8x8_halfpel_h_asm_dm642  .cproc
A_dst0, B_src0, A_stride,B_stride
.no_mdep              ;存储区没有依赖性,这样便于流水
.reg  B_src1_FIX_F, B_src1_FEDC:B_src1_BA98,
B_src1_GFED, B_src1_CBA9 ;定义的寄存器
.reg  A_src0_FIX_7, A_src0_7654:A_src0_3210, A_src0_8765, A_src0_4321
.reg  B_dst1_FEDC:B_dst1_BA98, A_dst0_7654:A_
dst0_3210
.reg  B_dst1, A_src1, A_i, A_pitch,B_pitch
MVK 3,      A_i               ;循环次数
ADD  B_src0,  B_stride,  A_src1 ;
ADD  A_dst0,  A_stride, B_dst1 ;
SHR  A_stride,  2,   A_pitch
SHR  B_stride,  2,  B_pitch
mc8x8_hpel_h: .trip 4, 4, 4                
 ; 每次处理两行,循环4次
LDNW  .D1T2   *+A_src1[2],   B_src1_FIX_F   ; 地址不对齐读取
LDNDW  .D1T2   *A_src1++[B_pitch], B_src1_FEDC:B_src1_BA98 ;
;;
SHRMB .2 B_src1_FIX_F, B_src1_FEDC, 
B_src1_GFED ;右移并拼接:fix_F || (FEDC>>8)
;;    AVGU4 .2  B_src1_FEDC, B_src1_GFED,
B_dst1_FEDC ; 4对字节对应取平均值
    ;;
STDW .D2T2   B_dst1_FEDC:B_dst1_BA98,
*B_dst1++[A_pitch] ; 存结果
;;
[A_i] BDEC             mc8x8_hpel_h, A_i
.return
.endproc

上述代码首先使用地址不对齐指令读取数据源。然后右移并拼接形成4字节,接着取4对字节对应求平均,最后存储结果。每次处理两行,循环4次。

2.垂直方向插值补偿

垂直方向插值的原理是图像块的第0行、第1行的元素对应取平均,结果放置在新块的第0行,图像块的第1行、第2行的元素对应取平均,结果放置新块的第1行,依次类推,直到处理完整个图像块,新块即为垂直插值补偿块。C语言代码如下。

void interpolate8x8_halfpel_v(uint8_t* const dst,const uint8_t* const src, 
const uint32_t stride, const uint32_t rounding)
{
uint32_t j;
int r = 1 - rounding;
for (j = 0; j < 8*stride; j+=stride)                        //每次循环处理一行
{
dst[j + 0] = (uint8_t)((src[j + 0] + src[j + stride + 0] + r )>>1);
//0元素和次行0元素取平均
dst[j + 1] = (uint8_t)((src[j + 1] + src[j + stride + 1] + r )>>1);
//1元素和次行1元素取平均
dst[j + 2] = (uint8_t)((src[j + 2] + src[j + stride + 2] + r )>>1);
//2元素和次行2元素取平均
dst[j + 3] = (uint8_t)((src[j + 3] + src[j + stride + 3] + r )>>1);
//3元素和次行3元素取平均
dst[j + 4] = (uint8_t)((src[j + 4] + src[j + stride + 4] + r )>>1);
//4元素和次行4元素取平均
dst[j + 5] = (uint8_t)((src[j + 5] + src[j + stride + 5] + r )>>1);
//5元素和次行5元素取平均
dst[j + 6] = (uint8_t)((src[j + 6] + src[j + stride + 6] + r )>>1);
//6元素和次行6元素取平均
dst[j + 7] = (uint8_t)((src[j + 7] + src[j + stride + 7] + r )>>1);
//7元素和次行7元素取平均
}
}
【责任编辑:云霞 TEL:(010)68476606】

回书目   上一节   下一节

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇14.2.3 DM642下XviD CODEC优化(2.. 下一篇14.3.1 YUV原始视频数据及其显示

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: