Chinaunix首页 | 论坛 | 博客
  • 博客访问: 45508
  • 博文数量: 4
  • 博客积分: 240
  • 博客等级: 入伍新兵
  • 技术积分: 115
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-03 14:51
文章分类

全部博文(4)

文章存档

2013年(1)

2012年(3)

我的朋友

分类: C/C++

2013-01-31 10:21:42

不完整,待编辑


h264toRTP.h

#ifndef _H264TORTP_H
#define	_H264TORTP_H

#include 

/* Payload type */
#define	H264 	96

/* Timestamp */
#define CLKRATE		90000.0
#define SAMPLING	CLKRATE

/*
 *	RTP HEADER : little-endian
 */
typedef struct RTP_HEADER{
	/* byte 0 */
	uint8_t		csrc_len:	4;	/* bit: 0~3 */
	uint8_t		extension:	1;	/* bit: 4 */
	uint8_t		padding:	1;	/* bit: 5 */
	uint8_t		version:	2;	/* bit: 6~7 */
	/* byte 1 */
	uint8_t		payload:	7;	/* bit: 0~6 */
	uint8_t		marker:		1;	/* bit: 7 */
	/* byte 2 ~ 3 */
	uint16_t	seq_no;
	/* byte 4 ~ 7 */
	uint32_t	timestamp;
	/* byte 8 ~ 11 */
	uint32_t	ssrc;
} __attribute__ ((packed)) RTP_HEADER_t;	/* 12 bytes */


/*
 * All NAL units consist of a single NAL unit type octet, 
 * which also co-serves as the payload header of this RTP payload format.
 *
 *		+---------------+
 *		|0|1|2|3|4|5|6|7|
 *		+-+-+-+-+-+-+-+-+
 *		|F|NRI|  Type   |
 *		+---------------+
 *
 *	*	TYPE:5 bits@nal_unit_type.
 *
 *	*	NRI:2 bits@nal_ref_idc. The semantics of value 00 and a non-zero value
 *		remain unchanged from the H.264 specification. In other words, a value
 *		of 00 indicates that the content of the NAL unit is not used to reconstruct
 *		reference pictures for inter picture prediction. Such NAL units can be
 *		discarded without risking the integrity of the reference pictures.Values
 *		greater than 00 indicate that the decoding of the NAL unit is required 
 *		to maintain the integrity of the reference pictures.In addition to the
 *		specification above, according to this RTP payload specification, values
 *		of NRI greater than 00 indicate the relative transport priority,as determined
 *		by the encoder. MANEs can use this information to protect more important 
 *		NAL units better than they do less important NAL units.The highest transport
 *		priority is 11, followed by 10, and then by 01; finally,00 is the lowest.
 *
 *	*	F:1 bit@forbidden_zero_bit. A value of 0 indicates that the NAL unit type
 *		octet and payload should not contain bit errors or other syntax violations. 
 *		A value of 1 indicates that the NAL unit type octet and payload may contain 
 *		bit errors or other syntax violations.
 */
typedef struct NALU_HEADER{
	/* byte 0 */
	uint8_t TYPE:	5;	/* bit: 0~4 */
	uint8_t NRI:	2;	/* bit: 5~6 */
	uint8_t F:		1;	/* bit: 7 */
} __attribute__ ((packed)) NALU_HEADER_t;	/* 1 bytes */


/*
 *
 */
typedef struct FU_INDICATOR {
    /* byte 0 */
	uint8_t TYPE:	5;	/* bit: 0~4 */
	uint8_t NRI:	2;	/* bit: 5~6 */
	uint8_t F:		1;	/* bit: 7 */
} __attribute__ ((packed)) FU_INDICATOR_t; /* 1 bytes */


/*
 *
 */
typedef struct FU_HEADER {
	/* byte 0 */
	uint8_t TYPE:	5;	/* bit: 0~4 */
	uint8_t R:		1;	/* bit: 5 */
	uint8_t E:		1;	/* bit: 6 */
	uint8_t S:		1;	/* bit: 7 */
} __attribute__ ((packed)) FU_HEADER_t;	/* 1 bytes */


/*
 *
 */
typedef struct NALU {
	unsigned int	nal_unit_type;
	unsigned int	nal_ref_idc;
	unsigned int	forbidden_zero_bit;
	unsigned int	nalu_size;
	unsigned int	nalu_offset;
	char			*nalu_pbuf;
} NALU_t;


NALU_t *NALU_create(int size);

void NALU_delete(NALU_t *nalu);

int NALU_getPayload(NALU_t *nalu, char *pNalu);

#endif

rtp_test.c

#include 
#include 
#include 
#include 
#include 

#include 
#include 

#include "h264toRTP.h"
#include "rtcp.h"

#define	BUFFSIZE	1500
#define MTU_SIZE	1400

typedef struct sockaddr SA;

/* Test file name */
char  h264_file[] = "zhizuxia.264";
//char  h264_file[] = "ti704_576.264";
//char  h264_file[] = "idrnew2.264";

FILE *videoFile;

static int locate_start_flags(char pbuf[])
{
	if(pbuf[0] != 0 
		|| pbuf[1] != 0 
		|| pbuf[2] != 0 
		|| pbuf[3] != 1)	return 0;

 	else	return 1;
}

NALU_t *NALU_create(int size)
{
	NALU_t 	 *nalu;

	nalu = (NALU_t *)calloc(1, sizeof(NALU_t));
	if (NULL == nalu) {
		fprintf(stderr, "Failed to alloc space for NALU\n");
		free(nalu);
		return NULL;
	}

	nalu->nalu_pbuf= (char *)calloc(1, size);
	if (NULL == nalu->nalu_pbuf) {
		fprintf(stderr, "Failed to alloc spaces for data.\n");
		free(nalu);
		return NULL;
	}

	nalu->nalu_size 	= size;
	nalu->nalu_offset 	= 0;

	return nalu;
}

void NALU_delete(NALU_t *nalu)
{
	if (nalu) {
		if (nalu->nalu_pbuf) {
			free(nalu->nalu_pbuf);
			nalu->nalu_pbuf = NULL;
		}
		free(nalu);
		nalu = NULL;
	}
}

int NALU_getPayload(NALU_t *nalu, char *pNalu)
{
	int  pos, flag = 0;

	memset(pNalu, 0, 2000000);

	if (4 != fread(pNalu, 1, 4, videoFile)) {
		fprintf(stderr, "Read start codes ERROR\n");
		return -1;
	}
	else {
		pos = 4;
	}

	if (!locate_start_flags(&pNalu[0])) {
		fprintf(stderr, "start codes not found\n");
		return -1;
	}

	while (!flag) {
		if(feof(videoFile)) {
			nalu->nalu_size = (pos - 1) - 4;
			memcpy (nalu->nalu_pbuf, &pNalu[4], nalu->nalu_size);

			nalu->forbidden_zero_bit 		= nalu->nalu_pbuf[0] & 0x80;
			nalu->nal_ref_idc 		= nalu->nalu_pbuf[0] & 0x60;
			nalu->nal_unit_type = nalu->nalu_pbuf[0] & 0x1f;

			return (pos - 1);
		}
		pNalu[pos++] = fgetc(videoFile);
		flag = locate_start_flags(&pNalu[pos - 4]);
	}

	if (0 != fseek(videoFile, -4, SEEK_CUR)) {
		fprintf(stderr, "Cannot fseek in the video stream file\n");
	}


	nalu->nalu_size = (pos - 4) - 4;
	printf("data size : %d\n", nalu->nalu_size);
	memcpy(nalu->nalu_pbuf, &pNalu[4], nalu->nalu_size);

	nalu->forbidden_zero_bit = nalu->nalu_pbuf[0] & 0x80;
	nalu->nal_ref_idc 		 = nalu->nalu_pbuf[0] & 0x60;
	nalu->nal_unit_type 	 = nalu->nalu_pbuf[0] & 0x1f;

	return (pos - 4);
}

int main(int argc, char *argv[])
{
	unsigned short		seq_num			= 0;
	unsigned int		ts_incremental 	= 0;
	unsigned int		ts_current		= 0;
	float 				framerate 		= 25;
	int 				bytes			= 0;
	int 				connfd			= -1;
	NALU_t				*nalu 			= NULL;
	RTP_HEADER_t		*rtp_hdr 		= NULL;
	NALU_HEADER_t		*nalu_hdr 		= NULL;
	FU_INDICATOR_t		*fu_indicator 	= NULL;
	FU_HEADER_t			*fu_hdr 		= NULL;
	char				*pNalu 			= NULL;
	char				buf[BUFFSIZE]	= {0,};
	struct sockaddr_in	peeraddr;
	int 				i, j, k;
	int 				count = 0, n = 0;

	printf("starting prog ...\n");

	videoFile = fopen(h264_file, "rb");
	if (NULL == videoFile) {
		fprintf(stderr, "cannot open h264 video file: %s\n", h264_file);
		goto cleanup;
	}

	nalu = NALU_create(4000000);
	if (NULL == nalu) {
		fprintf(stderr, "Failed to create NALU OBJECT\n");
		goto cleanup;
	}

	pNalu = (char *)calloc(2000000, sizeof(char));
	if (NULL == pNalu) {
		fprintf(stderr, "Failed to alloc tmpe space for nalu\n");
		goto cleanup;
	}

	connfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (-1 == connfd) {
		fprintf(stderr, "failed to create socket\n");
		goto cleanup;
	}

	bzero(&peeraddr, sizeof(peeraddr));
	peeraddr.sin_family = AF_INET;
	peeraddr.sin_port = htons(atoi("8888"));
	peeraddr.sin_addr.s_addr = inet_addr("192.168.0.78");

	/* timesampe increasment */
	ts_incremental = (unsigned int)(SAMPLING / framerate);

	while (!feof(videoFile)) {

		memset(buf, 0, BUFFSIZE);
		memset(nalu->nalu_pbuf, 0, nalu->nalu_size);

		rtp_hdr = (RTP_HEADER_t *)&buf[0]; 
		rtp_hdr->payload = H264;
		rtp_hdr->version = 2;
		rtp_hdr->marker  = 0;
		rtp_hdr->ssrc	 = htonl(10);

		n = NALU_getPayload(nalu, pNalu);
		printf("%d, %d\n", ++count, n);

		/*
		 *	Fragmentation unit: Used to fragment a single NAL unit over multiple RTP packets. 
		 *	Exists with two versions, FU-A and FU-B, identified with the NAL unit type numbers 28 and 29, respectively.
		 */
		if (nalu->nalu_size > MTU_SIZE) {
			ts_current = ts_current + ts_incremental;
			rtp_hdr->timestamp = htonl(ts_current);

			/* */
			j = nalu->nalu_size / MTU_SIZE;
			/* */
			k = nalu->nalu_size % MTU_SIZE;

			printf("%d, %d\n", j, k);

			for (i = 0; i <= j; i++) {
				rtp_hdr->seq_no	= htons(seq_num ++);

				if (0 == i) {
					printf("the 1st\n");
					rtp_hdr->marker = 0;

					fu_indicator 		= (FU_INDICATOR_t *)&buf[12];
					fu_indicator->F 	= nalu->forbidden_zero_bit;
					fu_indicator->NRI 	= nalu->nal_ref_idc >> 5;
					fu_indicator->TYPE 	= 28;

					fu_hdr = (FU_HEADER_t *)&buf[13];
					fu_hdr->E = 0;
					fu_hdr->R = 0;
					fu_hdr->S = 1;
					fu_hdr->TYPE = nalu->nal_unit_type;

					memcpy(&buf[14], nalu->nalu_pbuf + 1, MTU_SIZE);
					
					bytes = MTU_SIZE + 14;
					sendto(connfd, buf, bytes, 0, (SA *)&peeraddr, sizeof(peeraddr));
				}
				else if (j == i) {
					printf("the last\n");
					rtp_hdr->marker = 1;

					fu_indicator 		= (FU_INDICATOR_t *)&buf[12];
					fu_indicator->F 	= nalu->forbidden_zero_bit;
					fu_indicator->NRI 	= nalu->nal_ref_idc >> 5;
					fu_indicator->TYPE 	= 28;

					fu_hdr = (FU_HEADER_t *)&buf[13];
					fu_hdr->E = 1;
					fu_hdr->R = 0;
					fu_hdr->S = 0;
					fu_hdr->TYPE = nalu->nal_unit_type;

#if 0
					if (k == 0) {
						bytes = MTU_SIZE + 14;
						memcpy(&buf[14], nalu->nalu_pbuf + i * MTU_SIZE + 1, MTU_SIZE);
						sendto(connfd, buf, bytes, 0, (SA *)&peeraddr, sizeof(peeraddr));
					}
					else{
						bytes = k- 1 + 14;
						memcpy(&buf[14], nalu->nalu_pbuf + i * MTU_SIZE + 1, k - 1);
						sendto(connfd, buf, bytes, 0, (SA *)&peeraddr, sizeof(peeraddr));
					}

#endif
					if (k == 0)	break;

					bytes = k- 1 + 14;
					memcpy(&buf[14], nalu->nalu_pbuf + i * MTU_SIZE + 1, k - 1);
					sendto(connfd, buf, bytes, 0, (SA *)&peeraddr, sizeof(peeraddr));

					/* control the rate of sending frame */
					usleep(35000);
				}
				else {
					printf("############\n");
					rtp_hdr->marker = 0;

					fu_indicator 		= (FU_INDICATOR_t *)&buf[12];
					fu_indicator->F 	= nalu->forbidden_zero_bit;
					fu_indicator->NRI 	= nalu->nal_ref_idc >> 5;
					fu_indicator->TYPE 	= 28;

					fu_hdr = (FU_HEADER_t*)&buf[13];
					fu_hdr->E = 0;
					fu_hdr->R = 0;
					fu_hdr->S = 0;
					fu_hdr->TYPE = nalu->nal_unit_type;

					memcpy(&buf[14], nalu->nalu_pbuf + i * MTU_SIZE + 1, MTU_SIZE);

					bytes = MTU_SIZE + 14;	
					sendto(connfd, buf, bytes, 0, (SA *)&peeraddr, sizeof(peeraddr));
				}
			}

		}
		/*
		 *	Single NAL Unit Packet: Contains only a single NAL unit in the payload. 
		 *	The NAL header type field will be equal to the original NAL unit type.
		 */
		else {
			printf("***********\n");
			ts_current = ts_current + ts_incremental;
			rtp_hdr->timestamp = htonl(ts_current);
			rtp_hdr->marker	= 1;
			rtp_hdr->seq_no	= htons(seq_num ++);

			nalu_hdr = (NALU_HEADER_t *)&buf[12];
			nalu_hdr->F 	= nalu->forbidden_zero_bit;
			nalu_hdr->NRI 	= nalu->nal_ref_idc >> 5;
			nalu_hdr->TYPE 	= nalu->nal_unit_type;
		
			memcpy(&buf[13], nalu->nalu_pbuf + 1, nalu->nalu_size - 1);
		
			bytes = nalu->nalu_size + 12 ;	
			sendto(connfd, buf, bytes, 0, (SA *)&peeraddr, sizeof(peeraddr));
		}
	}

cleanup:
	printf("ending prog ... \n");

	close(connfd);

	if (nalu) {
		NALU_delete(nalu);
	}

	if (pNalu) {
		free(pNalu);
	}

	if (videoFile) {
		fclose(videoFile);
	}

	return 0;
}

阅读(2115) | 评论(0) | 转发(0) |
0

上一篇:搭建达芬奇DSP Server

下一篇:没有了

给主人留下些什么吧!~~