DSP编程中的字节对齐

PC上向ADI DSP平台移植时,经常会出现一些问题,其中很多问题和字节对齐有关。这类问题往往在PC上测试成功,在DSP上也能成功编译链接,但是运行却会出错,导致这类问题很难查出并解决。

问题成因:

我使用的是ADIBlackfin系列DSP,不知道其他平台是否有这个规定。就是char型数据类型地址可以任意,short型数据类型地址必须被2整除,int型数据类型地址必须被4整除,依此类推,即基础数据类型的地址必须被这种数据类型的大小整除。

而一般PC上是没有这个规定的。于是问题来了,比如下面的取数据函数,在PC上没有问题,在ADI DSP上运行肯定会出错的。

void get_data(unsigned char *inbuf)

{

char data1;

short data2;

int data3;

data2 = *(((short *)inbuf)++);      //1

data1 = *(inbuf++);              //2

data3 = *((int *)inbuf);           //3

 

fprintf(stdout, “data1 = %d/ndata2 = %d/ndata3 = %d/n”, data1, data2, data3);

return;

}

根据上面的规定,显然不论输入的inbuf地址是多少,上面的程序都会出错。比如说inbuf是奇数,句1就是将一个奇数地址强制转换成了一个short型地址,出错。如果inbuf是偶数,经过句1和句2后,句3显然又将一个奇数地址强制转换成了一个int型的地址,出错。

这种问题不是我特意设置来钻牛角尖的,他普遍存在于从码流中读入不同类型的数据的程序中,比如音视频解析对码流的解析,码流中存在各种数据类型的语法元素,将他们读入内存的时候就有这种问题。

 

解决方法:

方法1

将一个长数据类型,分解成几个char类型来读取,比如一个int型的数据可以这样读取:

//original

unsigned char* inbuf;                          //注意一定是unsiged

unsigned int tmp1, tmp2, tmp3, tmp4;

int res;

tmp1 = (unsigned int)*(inbuf++);

tmp2 = (unsigned int)*(inbuf++);

tmp3 = (unsigned int)*(inbuf++);

tmp4 = (unsigned int)*(inbuf++);

res = (int)((tmp1 & 0xff) + ((tmp2 & 0xff)<<8) + ((tmp3 & 0xff)<<16) + ((tmp4 & 0xff)<<24));

 

//or macro

#define GetUnalignedDword( pb, dw ) /

            (dw) = ((unsigned int) *(pb + 3) << 24) + /

                   ((unsigned int) *(pb + 2) << 16) + /

                   ((unsigned int) *(pb + 1) << 8) + *pb;

方法2

定义一个包含基础数据类型的紧缩的结构体,将不对齐地址强制转化成此结构体,示例如下

#ifdef __GNUC__

#define GNUC_PACKED   __attribute__ ((packed))

#else

#define GNUC_PACKED

#endif

 

#ifdef __arm

#define ARM_PACKED     __packed

#else

#define ARM_PACKED

#endif

 

#if defined WIN32 || defined VDSP

#pragma pack(1)

#endif

ARM_PACKED struct unaligned_32 { unsigned int data; } GNUC_PACKED;

#if defined WIN32 || defined VDSP

#pragma pack()

#endif

//struct defined upper

 

int data;

data = ((struct unaligned_32 *)inbuf)->data;

 

方法2节省一些计算,不过一般来说码流解析不是主要占用系统资源的模块,不需要很高的效率。建议两种方法都可以试试,再根据实际的效果来选取效果最好的。

 

参考文章:http://blog.csdn.net/fmddlmyy/archive/2008/07/16/2663481.aspx

 

附:声明对齐数据类型的方法(摘自ffmpeg

#if defined(__ICC) || defined(__SUNPRO_C)

    #define DECLARE_ALIGNED(n,t,v)      t v __attribute__ ((aligned (n)))

    #define DECLARE_ASM_CONST(n,t,v)    const t __attribute__ ((aligned (n))) v

#elif defined(__GNUC__)

    #define DECLARE_ALIGNED(n,t,v)      t v __attribute__ ((aligned (n)))

    #define DECLARE_ASM_CONST(n,t,v)    static const t v attribute_used __attribute__ ((aligned (n)))

#elif defined(_MSC_VER)

    #define DECLARE_ALIGNED(n,t,v)      __declspec(align(n)) t v

    #define DECLARE_ASM_CONST(n,t,v)    __declspec(align(n)) static const t v

#else

    #define DECLARE_ALIGNED(n,t,v)      t v

    #define DECLARE_ASM_CONST(n,t,v)    static const t v

#endif

ffmpegDECLARE_ALIGNED宏只用于数据类型和数组,我认为他的作用在于将数据或数组的首地址按照参数n来对齐,n单位为byte。至于他能否用于结构体,我不知道……估计也是可以的。

你可能感兴趣的:(DSP编程中的字节对齐)