1 union巧妙地实现多字节数据类型之间的转化
在涉及音视频编解码算法中,经常会涉及一些数据压缩、声音解码、图象的缩放等问题。
这里通过一个例子来推荐一种union绝妙用法(这种方法由Equator公司提供,在我们公司的图象处理算法中用得很多)。在该例子中,利用union结构n64u实现占8个字节n64类型与单字节的c0~c7的相互转换,从而达到数据压缩和分解的目的。
#include <stdio.h>
#define IN
#define OUT
#define INOUT
typedefunsigned long longn64;
typedef unsigned int n32;
typedef unsigned shortn16;
typedef unsigned charn8;
typedef struct_s8t{
unsigned charc0, c1, c2, c3, c4, c5, c6, c7;
}s8t;
typedefunion{
n64n64;
struct {
n32 l0, l1;
}u32;
struct {
long l0, l1;
} s32;
struct {
unsigned short s0, s1, s2, s3;
} u16;
struct {
short s0, s1, s2, s3;
} s16;
struct {
unsigned char c0, c1, c2, c3, c4, c5, c6, c7;
}u8;
struct {
char c0, c1, c2, c3, c4, c5, c6, c7;
} s8;
}n64u;
#defineMAX_DATA_COMPRESSED_NUM8
intcompress64_8(IN constn64* src,IN n16 n,OUT n8* dst);
intuncompress8_64(IN const n8* src,IN n16 n,OUT n64* dst);
intcompress64_8(IN const n64* src,IN n16 n,OUT n8* dst)
{
n64u n64u_data;
registern64* n64ptr=(n64*)src;
registern8* n8ptr=dst;
n16 i=0,num=n;
if(NULL==n64ptr || NULL==n8ptr || n<1)
{
printf("invalid param,src 0x%x,dst 0x%x,n %dn",n64ptr,n8ptr,n);
return 0;
}
for(i=0;i<num;i++)
{
n64u_data.n64 = *n64ptr++;
*n8ptr++ = (n64u_data.u8.c0+n64u_data.u8.c1+n64u_data.u8.c2+
n64u_data.u8.c3+n64u_data.u8.c4+n64u_data.u8.c5+
n64u_data.u8.c6+n64u_data.u8.c7)/(sizeof(n64)/sizeof(n8));
}
return 1;
}
int uncompress8_64(IN const n8* src,IN n16 n,OUT n64* dst)
{
n64u n64u_data;
register n64* n64ptr=dst;
register n8* n8ptr=(n8*)src;
register n8n8data;
n16 i=0,num=n;
if(NULL==n64ptr || NULL==n8ptr || n<1)
{
printf("invalid param,src 0x%x,dst 0x%x,n %dn",n64ptr,n8ptr,n);
return 0;
}
for(i=0;i<num;i++)
{
n8data=*n8ptr++;
n64u_data.u8.c0 = n8data;
n64u_data.u8.c1 = n8data;
n64u_data.u8.c2 = n8data;
n64u_data.u8.c3 = n8data;
n64u_data.u8.c4 = n8data;
n64u_data.u8.c5 = n8data;
n64u_data.u8.c6 = n8data;
n64u_data.u8.c7 = n8data;
*n64ptr++ = n64u_data.n64;
}
}
int main(int argc, char *argv[])
{
n64n64data[MAX_DATA_COMPRESSED_NUM];
n8n8data[MAX_DATA_COMPRESSED_NUM];
s8ts8t_data[MAX_DATA_COMPRESSED_NUM]
=
{
{1,2,3,4,5,6,7,8},
{2,2,3,4,5,6,7,7},
{3,2,3,4,5,6,7,6},
{4,2,3,4,5,6,7,5},
{5,2,3,4,5,6,7,4},
{6,2,3,4,5,6,7,3},
{7,2,3,4,5,6,7,2},
{8,7,6,5,4,3,2,1}
};
n16 i,n=MAX_DATA_COMPRESSED_NUM;
printf("data:n");
for(i=0;i<n;i++)
{
n64data[i] = *(n64*)&s8t_data[i];
printf("%3u %3u %3u %3u %3u %3u %3u %3un",
s8t_data[i].c0,s8t_data[i].c1,s8t_data[i].c2,
s8t_data[i].c3,s8t_data[i].c4,s8t_data[i].c5,
s8t_data[i].c6,s8t_data[i].c7);
}
printf("n");
compress64_8(n64data,n,n8data);
printf("compressed to:n");
for(i=0;i<n;i++)
{
printf("%3u ",n8data[i]);
}
printf("nn");
uncompress8_64(n8data,n,n64data);
printf("uncompressed to:n");
for(i=0;i<n;i++)
{
*(n64*)&s8t_data[i] = n64data[i];
printf("%3u %3u %3u %3u %3u %3u %3u %3un",
s8t_data[i].c0,s8t_data[i].c1,s8t_data[i].c2,
s8t_data[i].c3,s8t_data[i].c4,s8t_data[i].c5,
s8t_data[i].c6,s8t_data[i].c7);
}
printf("n");
}
2.使不同数据包兼容
union的用法如下:
struct _my_struct
{
unsigned int struct_id
typedef union _my_union
{
struct my_struct_1;
struct my_struct_2;
struct my_struct_3;
}my_union;
}my_struct;
我们公司在处理音频视频数据流方面,为了区分音频和视频数据以及来自网络和编解码的数据并减少内存占用使用了下面的数据结构。这种union使用方法在网络应用中特别常见。在数据结构TFrameBufferInfo中,用bufferType标识数据来源。
typedef struct
{
intcodecId;
intpacketNum;
intactualNum;
intpacketLen;
intleftPacketLen;
intframeSample;
inttimeStamp;
intdataLen;
intready;
unsigned char*buffer;
intreserve1;
} TABufferInfoFromCodec;
typedef struct
{
intcodecId;
intbKeyFrame;
intpacketNum;
intactualNum;
intpacketLen;
intleftPacketLen;
inttimeStamp;
intdataLen;
intready;
unsigned char*buffer;
intreserve1;
} TVBufferInfoFromCodec;
typedef struct
{
intcodecId;
intbKeyFrame;
intpacketNum;
intactualNum;
intpacketLen;
intleftPacketLen;
intrtpLen;
inttimeStamp;
intfirstSquence;
intdataLen;
intready;
unsigned char*buffer;
} TVBufferInfoToCodec;
typedef struct
{
intcodecId;
intpacketNum;
intactualNum;
intpacketLen;
intleftPacketLen;
intrtpLen;
inttimeStamp;
intfirstSquence;
intdataLen;
intready;
unsigned char*buffer;
intreserve1;
} TABufferInfoToCodec;
typedef struct
{
intbufferType;
union
{
TVBufferInfoFromCodecbufferInfoFromVCoder;
TABufferInfoFromCodecbufferInfoFromACoder;
TVBufferInfoToCodecbufferInfoFromVNetWork;
TABufferInfoToCodecbufferInfoFromANetWork;
} buffer_info;
} TFrameBufferInfo;
int send_to(void* stream);
intsend_to(void* stream)
{
}
int main(int argc, char *argv[])
{
TFrameBufferInfo tFrameBufferInfo;
TVBufferInfoFromCodec* pVBufferInfoFromCodec;
unsigned char buffer[1200*5];
tFrameBufferInfo.bufferType=4;
pVBufferInfoFromCodec
=&tFrameBufferInfo.buffer_info.bufferInfoFromVCoder;
pVBufferInfoFromCodec->bKeyFrame= 1;
pVBufferInfoFromCodec->packetNum= 2;
pVBufferInfoFromCodec->actualNum= 2;
pVBufferInfoFromCodec->leftPacketLen= 123;
pVBufferInfoFromCodec->dataLen= 1323;
pVBufferInfoFromCodec->ready= 1;
pVBufferInfoFromCodec->buffer= buffer;
send_to((void*)&tFrameBufferInfo);
}