c++之bit写数据到内存中

发布于:2022-11-07 ⋅ 阅读:(1079) ⋅ 点赞:(0)

系列文章目录



前言


一、bit位写数据?

在通信行业或者音视频行业,通常数据格式是以bit来计算的,不同位置的bit位代表着不同的含义。因此bit为数据的写入对于c++开发尤为重要,本文将介绍一种实现的demo,来写rtp数据,rtp包格式如下:

在这里插入图片描述
V : 2bits,表示版本号
P : 1bit,表示是否支持填充,置为1的时候,表示在packet的末尾进行填充,方便一些针对固定长度算法的封装
X : 1bit, 表示是否支持Rtp头扩展,置为1的时候,RtpHeader以后会跟1个header extension
CC (CSRC count): 4bits,表示头部以后contributing sources identifiers的个数
M : 1bit;对于视频,标记一帧的结束;对于音频,标记会话的开始
PT : 7bits,表示传输的多媒体类型,(https://tools.ietf.org/html/rfc3551)
sequence number :16bits(2字节),表示RTP包序号
timestamp :32bits(4字节),表示时间戳, 必须使用90 kHz 时钟频率
SSRC :32bits(4字节),用于标识同步信源,参加同一视频会议的两个同步信源不能有相同的SSRC
CSRC :特约信源标识符,每一个CSRC占用4个字节,能够有0~15个。每一个CSRC标识了包含在该RTP报文有效载荷中的全部特约信源。

二、使用步骤

1.bit函数的实现

bits.h实现

#include <malloc.h>
#include <cstdint>
struct bits_buffer_t
{
	int     i_size;
	int     i_data;
	uint8_t i_mask;
	uint8_t *p_data;
};
typedef struct bits_buffer_t bits_buffer_t;

// 小端存储 低字节存低地址
// 10=0x0A --->内存中存储格式 0110 0000
static  void bits_write(struct bits_buffer_t *p_buffer, int bit_count, uint64_t i_bits)
{
	while (bit_count> 0){
		bit_count--;
		if ((i_bits >> bit_count) & 0x01){
			p_buffer->p_data[p_buffer->i_data] |= p_buffer->i_mask;  // 1
		}
		else{
			p_buffer->p_data[p_buffer->i_data] &= ~p_buffer->i_mask;// 0
		}
		//move right one bit from left to right 
		p_buffer->i_mask >>= 1; 
		//means one byte is over,then restart from begin
		if (p_buffer->i_mask == 0){
			p_buffer->i_data++;
			p_buffer->i_mask = 0x80;
		}
	}
}

2.rtp组包函数的实现

rtp实现

#include "bits.h"
#define RTP_HDR_LEN 12

/**
 * RTP头封装
 * @param pData buffer地址
 * @param seqNum 序号
 * @param timestamp 时间戳
 * @param ssrc 标识
 * @return
 */
int gb28181_make_rtp_header(char *pData, int seqNum, int64_t timestamp, int ssrc, int isEnd)
{
	bits_buffer_t bitsBuffer;
	bitsBuffer.i_size = RTP_HDR_LEN;
	bitsBuffer.i_data = 0;
	bitsBuffer.i_mask = 0x80;
	bitsBuffer.p_data = (unsigned char *)(pData);
	memset(bitsBuffer.p_data, 0, RTP_HDR_LEN);
	bits_write(&bitsBuffer, 2, 2);	            /*协议版本*/
	bits_write(&bitsBuffer, 1, 0);		        /*P*/
	bits_write(&bitsBuffer, 1, 0);		        /*X*/
	bits_write(&bitsBuffer, 4, 0);		        /*CSRC个数*/
	bits_write(&bitsBuffer, 1, isEnd);			/*一帧是否结束*/
	bits_write(&bitsBuffer, 7, 96); 		    /*载荷的数据类型*/
	bits_write(&bitsBuffer, 16, seqNum); 		/*序列号,第几个*/
	bits_write(&bitsBuffer, 32, timestamp);		/*时间戳,第一个 */
	bits_write(&bitsBuffer, 32, ssrc);			/*同步信源(SSRC)标识符*/
	return 0;
}

rtp header长度为12字节:
2+1+1+4 + 1+7 + 16 + 32 +32 = 12bytes

一次发送rtp包

char rtp_header[RTP_HDR_LEN];
int rtp_length = 3000; 
int single_packet_max_length = 1400;
int rtp_seq = 0;
int time_base = 90000;
int fps = 25;
int send_packet_interval = 1000 / fps;
int interval = time_base / fps;
int ssrc = 0xffffffff;
long pts = 0;

int rtp_packet_count = ((rtp_length - 1) / single_packet_max_length) + 1;
int single_packet_max_length = 1400;
for (int i = 0; i < rtp_packet_count; i++) {
	gb28181_make_rtp_header(rtp_header, rtp_seq, pts, ssrc, i ==(rtp_packet_count - 1));
	rtp_seq++;	
	//udp send
	//udp->send_packet
}
pts += interval;
std::this_thread::sleep_for(std::chrono::milliseconds(send_packet_interval ));


总结

通过以上例子,应该对bit的操作有了一定的理解,希望你能够从中受益。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到