协议按位赋值及解析总结

 

技术在于交流、沟通,转载请注明出处并保持作品的完整性。

原文:https://blog.csdn.net/hiwubihe/article/details/80736848

 

在协议开发时,经常需要按位赋值,如开发PS流封装时有一段PTS值赋值如下

 

协议按位赋值及解析总结_第1张图片

本篇以此字段为例子,总结一下赋值及解析的过程,代码部分参考VLC代码。直接上代码


/*******************************************************************************
Copyright (c) wubihe Tech. Co., Ltd. All rights reserved.
--------------------------------------------------------------------------------

Date Created:	2014-10-25
Author:			wubihe QQ:1269122125 Email:[email protected]
Description:	按位操作,赋值及解析
--------------------------------------------------------------------------------
Modification History
DATE          AUTHOR          DESCRIPTION
--------------------------------------------------------------------------------

********************************************************************************/

/*******************************************************************************
MPEG2-PS中有一段是对PES的PTS赋值到字节流中 

|----Type----|--Length(bit)--------------|--Description--------|
|  '0010'    |		4		 |	类型	       |
|PTS[32..30] |		3		 |PTS的30-32bit赋值     |
|marker_bit  |		1		 |标记位1	       |
|PTS[29..15] |		15		 |
|marker_bit  |		1		 |		
|PTS[14..0]  |		15		 |
|marker_bit  |		1		 |

********************************************************************************/
#include 
#include 
#include "bits.h"


#define BYTE_ORDER LITTLE_ENDIAN
#define BUFFER_SIZE		(64)



/这是解析用的结构体 打包数据采用网络字节序即大端方式组包 接收端如果是大端,则与网络字节序相同
#pragma pack(1)
typedef struct  
{// ts total 33 bits  
	//接收端如果是小端 则定义与协议中规定相反,因为协议是按照网络字节序组包的
#if (BYTE_ORDER == LITTLE_ENDIAN)  
	unsigned char fixed2        : 1;    // 固定为1  
	unsigned char ts1           : 3;    // bit30-32  
	unsigned char fixed1        : 4;    // DTS为0x01, PTS为0x02, PTS+DTS则PTS为0x03  

	unsigned char ts2;                  // bit22-29  
	unsigned char fixed3        : 1;    // 固定为1  
	unsigned char ts3           : 7;    // bit15-21  

	unsigned char ts4;                  // bit7-14  
	unsigned char fixed4        : 1;    // 固定为1  
	unsigned char ts5           : 7;    // bit0-6  
	//大端的情况 直接和协议网络字节序相同
#elif (BYTE_ORDER == BIG_ENDIAN)  
	unsigned char fixed1        : 4;    // DTS为0x01, PTS为0x02, PTS+DTS则PTS为0x03  
	unsigned char ts1           : 3;    // bit30-32  
	unsigned char fixed2        : 1;    // 固定为1  

	unsigned char ts2;                  // bit22-29  
	unsigned char ts3           : 7;    // bit15-21  
	unsigned char fixed3        : 1;    // 固定为1  

	unsigned char ts4;                  // bit7-14  
	unsigned char ts5           : 7;    // bit0-6  
	unsigned char fixed4        : 1;    // 固定为1  
#endif  
} PES_PTS_S;  
#pragma pack()


//#define FIRST__ 

int main()
{
	/第一种赋值方式///
#ifdef FIRST__
	char szBuffer[BUFFER_SIZE];
	memset(szBuffer,0,sizeof(szBuffer));

	size_t sDataLen = sizeof(PES_PTS_S);
	long long llPts = 786709;
	
	//这种赋值方式 安装大端赋值 网络字节序赋值
	bits_buffer_t bw;

	bits_initwrite (&bw, sDataLen, szBuffer);
	bits_write (&bw, 4, 0x01);
	bits_write (&bw, 3, (llPts >> 30)&0x07);
	bits_write (&bw, 1, 1);
	bits_write (&bw, 15, (llPts >> 15)&0x07FFF);
	bits_write (&bw, 1, 1);
	bits_write (&bw, 15, (llPts )&0x07FFF);
	bits_write (&bw, 1, 1);

	memcpy(szBuffer, bw.p_data, sDataLen);

	//取值过程
	PES_PTS_S stPts;
	memcpy(&stPts,szBuffer,sDataLen);
	long long llPtsValue;

	llPtsValue = (stPts.ts1 << 30)|(stPts.ts2 << 22) |(stPts.ts3 << 15)|(stPts.ts4 << 7)|(stPts.ts5 );
	
	

	printf("解析值:%ld\n",llPtsValue);
	
#else
	/第二种赋值方式///
	char szBuffer[BUFFER_SIZE];
	memset(szBuffer,0,sizeof(szBuffer));

	size_t sDataLen = sizeof(PES_PTS_S);
	long long llPts = 786709;

	PES_PTS_S sPts;
	sPts.fixed1 = 0x01;
	sPts.fixed2 = 0x01;
	sPts.fixed3 = 0x01;
	sPts.fixed4 = 0x01;
	sPts.ts1	= (llPts >> 30)&0x07;
	sPts.ts2	= (llPts >> 22)&0xFF;
	sPts.ts3	= (llPts >> 15)&0x7F;
	sPts.ts4	= (llPts >> 7)&0xFF;
	sPts.ts5	= (llPts )&0x7F;

	memcpy(szBuffer,&sPts,sDataLen);

	//取值过程
	PES_PTS_S stPts;
	memcpy(&stPts,szBuffer,sDataLen);
	long long llPtsValue;

	llPtsValue = (stPts.ts1 << 30)|(stPts.ts2 << 22) |(stPts.ts3 << 15)|(stPts.ts4 << 7)|(stPts.ts5 );



	printf("解析值:%ld\n",llPtsValue);
#endif
	getchar();
}

 

 

 

 

 

编译环境:   Win7_64bit+VS2008

DEMO下载地址:https://download.csdn.net/download/hiwubihe/10505021

大小端读取缓存示例

#include "stdint.h"
int avio_r8(unsigned char **p)

{

	return *(*p)++;

}







//读取小端16

unsigned int avio_rl16(unsigned char **p)

{

	unsigned int val;

	val = avio_r8(p);

	val |= avio_r8(p) << 8;

	return val;

}

//读取小端16

unsigned int avio_rl24(unsigned char **p)

{

	unsigned int val;

	val = avio_rl16(p);

	val |= avio_r8(p) << 16;

	return val;

}



unsigned int avio_rl32(unsigned char **p)

{

	unsigned int val;

	val = avio_rl16(p);

	val |= avio_rl16(p) << 16;

	return val;

}



uint64_t avio_rl64(unsigned char **p)

{

	uint64_t val;

	val = (uint64_t)avio_rl32(p);

	val |= (uint64_t)avio_rl32(p) << 32;

	return val;

}



unsigned int avio_rb16(unsigned char **p)

{

	unsigned int val;

	val = avio_r8(p) << 8;

	val |= avio_r8(p);

	return val;

}



unsigned int avio_rb24(unsigned char **p)

{

	unsigned int val;

	val = avio_rb16(p) << 8;

	val |= avio_r8(p);

	return val;

}

unsigned int avio_rb32(unsigned char **p)

{

	unsigned int val;

	val = avio_rb16(p) << 16;

	val |= avio_rb16(p);

	return val;

}

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(视频封装,C/C++基本知识)