技术在于交流、沟通,转载请注明出处并保持作品的完整性。
原文:https://blog.csdn.net/hiwubihe/article/details/80736848
在协议开发时,经常需要按位赋值,如开发PS流封装时有一段PTS值赋值如下
本篇以此字段为例子,总结一下赋值及解析的过程,代码部分参考VLC代码。直接上代码
/*******************************************************************************
Copyright (c) wubihe Tech. Co., Ltd. All rights reserved.
--------------------------------------------------------------------------------
Date Created: 2014-10-25
Author: wubihe QQ:1269122125 Email:1269122125@qq.com
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 <stdio.h>
#include <string.h>
#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;
}