C中Union的巧妙用法

C中Union的巧妙用法(转)

1 union巧妙地实现多字节数据类型之间的转化


在涉及音视频编解码算法中,经常会涉及一些数据压缩、声音解码、图象的缩放等问题。
     这里通过一个例子来推荐一种union绝妙用法(这种方法由Equator公司提供,在我们公司的图象处理算法中用得很多)。在该例子中,利用union结构n64u实现占8个字节n64类型与单字节的c0~c7的相互转换,从而达到数据压缩和分解的目的。

 

#include <stdio.h>

#define IN
#define OUT
#define INOUT

typedef unsigned long long  n64;
typedef unsigned int   n32;
typedef unsigned short  n16;
typedef unsigned char  n8;

 

typedef struct _s8t{
        unsigned char c0, c1, c2, c3, c4, c5, c6, c7;
}s8t;

 

 

typedef union {
        n64     n64;

        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;

 

#define MAX_DATA_COMPRESSED_NUM 8

 

int compress64_8(IN const n64* src,IN n16 n,OUT n8* dst);
int uncompress8_64(IN const n8* src,IN n16 n,OUT n64* dst);

 

int compress64_8(IN const n64* src,IN n16 n,OUT n8* dst)
{
 n64u n64u_data;
 register n64* n64ptr=(n64*)src;
 register n8* n8ptr=dst;
 n16 i=0,num=n;

 

 if(NULL==n64ptr || NULL==n8ptr || n<1)
 {
  printf("invalid param,src 0x%x,dst 0x%x,n %d\n",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 n8  n8data;
 n16 i=0,num=n;  
 
 if(NULL==n64ptr || NULL==n8ptr || n<1)
 {
  printf("invalid param,src 0x%x,dst 0x%x,n %d\n",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[])
{
 n64  n64data[MAX_DATA_COMPRESSED_NUM];
 n8   n8data[MAX_DATA_COMPRESSED_NUM];
 s8t  s8t_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 %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<n;i++)
 {
      printf("%3u ",n8data[i]);    
 
 printf("\n\n"); 
  
 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 %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.使不同数据包兼容

 

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
{
 int  codecId;         
 int  packetNum;       
 int  actualNum;       
 int  packetLen;         
 int  leftPacketLen;   
 int  frameSample;     
 int  timeStamp;       
 int  dataLen;         
 int  ready;           
 unsigned char* buffer; 
 int  reserve1;        


} TABufferInfoFromCodec;

 


typedef struct
{
 int  codecId;         
 int  bKeyFrame;       
 int  packetNum;       
 int  actualNum;       
 int  packetLen;         
 int  leftPacketLen;   
 int  timeStamp;        
 int  dataLen;         
 int  ready;            
 unsigned char* buffer; 
 int reserve1;         


} TVBufferInfoFromCodec;

 

 


typedef struct
{
 int  codecId;          
 int  bKeyFrame;       
 int  packetNum;       
 int  actualNum;       
 int  packetLen;       
 int  leftPacketLen;    
 int  rtpLen;           
 int  timeStamp;        
 int  firstSquence;     
 int  dataLen;          
 int  ready;           
 unsigned char* buffer;


} TVBufferInfoToCodec;

 


typedef struct
{
 int  codecId;          
 int  packetNum;        
 int  actualNum;        
 int  packetLen;        
 int  leftPacketLen;    
 int  rtpLen;           
 int  timeStamp;        
 int  firstSquence;     
 int  dataLen;          
 int  ready;            
 unsigned char* buffer; 
 int reserve1;         


} TABufferInfoToCodec;

 

 


typedef struct
{
 int bufferType;
 
 union
 
  TVBufferInfoFromCodec bufferInfoFromVCoder; 
  TABufferInfoFromCodec bufferInfoFromACoder; 
  TVBufferInfoToCodec bufferInfoFromVNetWork;
  TABufferInfoToCodec bufferInfoFromANetWork; 


 } buffer_info;
 
} TFrameBufferInfo; 
 

int send_to(void* stream);


int send_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);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值