1 union巧妙地實(shí)現(xiàn)多字節(jié)數(shù)據(jù)類型之間的轉(zhuǎn)化 在涉及音視頻編解碼算法中,,經(jīng)常會涉及一些數(shù)據(jù)壓縮,、聲音解碼、圖象的縮放等問題,。 這里通過一個例子來推薦一種union絕妙用法(這種方法由Equator公司提供,,在我們公司的圖象處理算法中用得很多)。在該例子中,,利用union結(jié)構(gòu)n64u實(shí)現(xiàn)占8個字節(jié)n64類型與單字節(jié)的c0~c7的相互轉(zhuǎn)換,,從而達(dá)到數(shù)據(jù)壓縮和分解的目的。 #include #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<> { printf('invalid param,src 0x%x,dst 0x%x,n %d\n',n64ptr,n8ptr,n); return 0; } for(i=0;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<> { printf('invalid param,src 0x%x,dst 0x%x,n %d\n',n64ptr,n8ptr,n); return 0; } for(i=0;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<> { n64data[i] = *(n64*)&s8t_data[i]; printf('%3u %3u %3u %3u %3u %3u %3u %3u\n', 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<> { printf('%3u ',n8data[i]); } printf('\n\n'); uncompress8_64(n8data,n,n64data); printf('uncompressed to:\n'); for(i=0;i<> { *(n64*)&s8t_data[i] = n64data[i]; printf('%3u %3u %3u %3u %3u %3u %3u %3u\n', 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.使不同數(shù)據(jù)包兼容 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; 我們公司在處理音頻視頻數(shù)據(jù)流方面,,為了區(qū)分音頻和視頻數(shù)據(jù)以及來自網(wǎng)絡(luò)和編解碼的數(shù)據(jù)并減少內(nèi)存占用使用了下面的數(shù)據(jù)結(jié)構(gòu),。這種union使用方法在網(wǎng)絡(luò)應(yīng)用中特別常見。在數(shù)據(jù)結(jié)構(gòu)TFrameBufferInfo中,,用bufferType標(biāo)識數(shù)據(jù)來源,。 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); }
|
|