同前篇类似,修改自vc下的程序,跟打包相反,原理就是从udp接收一个数据包,判断这个数据包是单个发送还是分片发送,进而获取rtp包中的h264NAL数据,并加上0x00000001起始字节一并写进文件中即可。
[cpp] view plain copy print ?
- #include <stdio.h>
-
- #include <stdlib.h>
-
- #include <string.h>
-
- #include <sys/socket.h>
-
- #include <netinet/in.h>
- #include <arpa/inet.h>
-
- #include <unistd.h>
-
- #include <errno.h>
-
- #include <sys/types.h>
-
- #include <fcntl.h>
-
- typedef struct
- {
- unsigned char version;
- unsigned char padding;
- unsigned char extension;
- unsigned char cc;
- unsigned char marker;
- unsigned char pt;
- unsigned int seq_no;
- unsigned int timestamp;
- unsigned int ssrc;
- unsigned char * payload;
- unsigned int paylen;
- } RTPpacket_t;
-
- typedef struct
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- unsigned char csrc_len:4;
- unsigned char extension:1;
- unsigned char padding:1;
- unsigned char version:2;
-
- unsigned char payloadtype:7;
- unsigned char marker:1;
-
- unsigned int seq_no;
-
- unsigned int timestamp;
-
- unsigned int ssrc;
- } RTP_FIXED_HEADER;
-
-
- typedef struct
- {
- unsigned char forbidden_bit;
- unsigned char nal_reference_idc;
- unsigned char nal_unit_type;
- unsigned int startcodeprefix_len;
- unsigned int len;
- unsigned int max_size;
- unsigned char * buf;
- unsigned int lost_packets;
- } NALU_t;
-
-
-
-
-
-
-
-
- typedef struct
- {
-
- unsigned char TYPE:5;
- unsigned char NRI:2;
- unsigned char F:1;
- } NALU_HEADER;
-
-
-
-
-
-
-
-
- typedef struct
- {
-
- unsigned char TYPE:5;
- unsigned char NRI:2;
- unsigned char F:1;
- } FU_INDICATOR;
-
-
-
-
-
-
-
-
- typedef struct
- {
-
- unsigned char TYPE:5;
- unsigned char R:1;
- unsigned char E:1;
- unsigned char S:1;
- } FU_HEADER;
-
- #define MAXDATASIZE 1500
- #define PORT 1234
- #define BUFFER_SIZE 10
-
- FILE * poutfile = NULL;
-
- char * outputfilename = "./receive.264";
-
- int OpenBitstreamFile (char *fn)
- {
- if (NULL == (poutfile = fopen(fn, "wb")))
- {
- printf("Error: Open input file error\n");
- getchar();
- }
- return 1;
- }
-
- NALU_t *AllocNALU(int buffersize)
- {
- NALU_t *n;
-
- if ((n = (NALU_t*)calloc (1, sizeof(NALU_t))) == NULL)
- {
- printf("AllocNALU Error: Allocate Meory To NALU_t Failed ");
- exit(0);
- }
- return n;
- }
-
- void FreeNALU(NALU_t *n)
- {
- if (n)
- {
- free (n);
- }
- }
-
-
-
-
-
- void rtp_unpackage(char *bufIn,int len)
- {
- unsigned char recvbuf[1500];
- RTPpacket_t *p = NULL;
- RTP_FIXED_HEADER * rtp_hdr = NULL;
- NALU_HEADER * nalu_hdr = NULL;
- NALU_t * n = NULL;
- FU_INDICATOR *fu_ind = NULL;
- FU_HEADER *fu_hdr= NULL;
- int total_bytes = 0;
- static int total_recved = 0;
- int fwrite_number = 0;
-
- memcpy(recvbuf,bufIn, len);
- printf("包长度+ rtp头: = %d\n",len);
-
-
-
-
- p = (RTPpacket_t*)&recvbuf[0];
- if ((p = malloc (sizeof (RTPpacket_t)))== NULL)
- {
- printf ("RTPpacket_t MMEMORY ERROR\n");
- }
- if ((p->payload = malloc (MAXDATASIZE))== NULL)
- {
- printf ("RTPpacket_t payload MMEMORY ERROR\n");
- }
-
- if ((rtp_hdr = malloc(sizeof(RTP_FIXED_HEADER))) == NULL)
- {
- printf("RTP_FIXED_HEADER MEMORY ERROR\n");
- }
-
- rtp_hdr =(RTP_FIXED_HEADER*)&recvbuf[0];
- printf("版本号 : %d\n",rtp_hdr->version);
- p->version = rtp_hdr->version;
- p->padding = rtp_hdr->padding;
- p->extension = rtp_hdr->extension;
- p->cc = rtp_hdr->csrc_len;
- printf("标志位 : %d\n",rtp_hdr->marker);
- p->marker = rtp_hdr->marker;
- printf("负载类型 :%d\n",rtp_hdr->payloadtype);
- p->pt = rtp_hdr->payloadtype;
- printf("包号 : %d \n",rtp_hdr->seq_no);
- p->seq_no = rtp_hdr->seq_no;
- printf("时间戳 : %d\n",rtp_hdr->timestamp);
- p->timestamp = rtp_hdr->timestamp;
- printf("帧号 : %d\n",rtp_hdr->ssrc);
- p->ssrc = rtp_hdr->ssrc;
-
-
-
-
- if (!(n = AllocNALU(800000)))
- {
- printf("NALU_t MMEMORY ERROR\n");
- }
- if ((nalu_hdr = malloc(sizeof(NALU_HEADER))) == NULL)
- {
- printf("NALU_HEADER MEMORY ERROR\n");
- }
-
- nalu_hdr =(NALU_HEADER*)&recvbuf[12];
- printf("forbidden_zero_bit: %d\n",nalu_hdr->F);
- n->forbidden_bit= nalu_hdr->F << 7;
- printf("nal_reference_idc: %d\n",nalu_hdr->NRI);
- n->nal_reference_idc = nalu_hdr->NRI << 5;
- printf("nal 负载类型: %d\n",nalu_hdr->TYPE);
- n->nal_unit_type = nalu_hdr->TYPE;
-
-
-
-
- if ( nalu_hdr->TYPE == 0)
- {
- printf("这个包有错误,0无定义\n");
- }
- else if ( nalu_hdr->TYPE >0 && nalu_hdr->TYPE < 24)
- {
- printf("当前包为单包\n");
- putc(0x00, poutfile);
- putc(0x00, poutfile);
- putc(0x00, poutfile);
- putc(0x01, poutfile);
- total_bytes +=4;
- memcpy(p->payload,&recvbuf[13],len-13);
- p->paylen = len-13;
- fwrite(nalu_hdr,1,1,poutfile);
- total_bytes += 1;
- fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);
- total_bytes = p->paylen;
- printf("包长度 + nal= %d\n",total_bytes);
- }
- else if ( nalu_hdr->TYPE == 24)
- {
- printf("当前包为STAP-A\n");
- }
- else if ( nalu_hdr->TYPE == 25)
- {
- printf("当前包为STAP-B\n");
- }
- else if (nalu_hdr->TYPE == 26)
- {
- printf("当前包为MTAP16\n");
- }
- else if ( nalu_hdr->TYPE == 27)
- {
- printf("当前包为MTAP24\n");
- }
- else if ( nalu_hdr->TYPE == 28)
- {
- if ((fu_ind = malloc(sizeof(FU_INDICATOR))) == NULL)
- {
- printf("FU_INDICATOR MEMORY ERROR\n");
- }
- if ((fu_hdr = malloc(sizeof(FU_HEADER))) == NULL)
- {
- printf("FU_HEADER MEMORY ERROR\n");
- }
-
- fu_ind=(FU_INDICATOR*)&recvbuf[12];
- printf("FU_INDICATOR->F :%d\n",fu_ind->F);
- n->forbidden_bit = fu_ind->F << 7;
- printf("FU_INDICATOR->NRI :%d\n",fu_ind->NRI);
- n->nal_reference_idc = fu_ind->NRI << 5;
- printf("FU_INDICATOR->TYPE :%d\n",fu_ind->TYPE);
- n->nal_unit_type = fu_ind->TYPE;
-
- fu_hdr=(FU_HEADER*)&recvbuf[13];
- printf("FU_HEADER->S :%d\n",fu_hdr->S);
- printf("FU_HEADER->E :%d\n",fu_hdr->E);
- printf("FU_HEADER->R :%d\n",fu_hdr->R);
- printf("FU_HEADER->TYPE :%d\n",fu_hdr->TYPE);
- n->nal_unit_type = fu_hdr->TYPE;
-
- if (rtp_hdr->marker == 1)
- {
- printf("当前包为FU-A分片包最后一个包\n");
- memcpy(p->payload,&recvbuf[14],len - 14);
- p->paylen = len - 14;
- fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);
- total_bytes = p->paylen;
- printf("包长度 + FU = %d\n",total_bytes);
- }
- else if (rtp_hdr->marker == 0)
- {
- if (fu_hdr->S == 1)
- {
- unsigned char F;
- unsigned char NRI;
- unsigned char TYPE;
- unsigned char nh;
- printf("当前包为FU-A分片包第一个包\n");
- putc(0x00, poutfile);
- putc(0x00, poutfile);
- putc(0x00, poutfile);
- putc(0x01, poutfile);
- total_bytes += 4;
-
- F = fu_ind->F << 7;
- NRI = fu_ind->NRI << 5;
- TYPE = fu_hdr->TYPE;
-
- nh = F | NRI | TYPE;
-
- putc(nh,poutfile);
-
- total_bytes +=1;
- memcpy(p->payload,&recvbuf[14],len - 14);
- p->paylen = len - 14;
- fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);
- total_bytes = p->paylen;
- printf("包长度 + FU_First = %d\n",total_bytes);
- }
- else
- {
- printf("当前包为FU-A分片包\n");
- memcpy(p->payload,&recvbuf[14],len - 14);
- p->paylen= len - 14;
- fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);
- total_bytes = p->paylen;
- printf("包长度 + FU = %d\n",total_bytes);
- }
- }
- }
- else if ( nalu_hdr->TYPE == 29)
- {
- if (rtp_hdr->marker == 1)
- {
- printf("当前包为FU-B分片包最后一个包\n");
-
- }
- else if (rtp_hdr->marker == 0)
- {
- printf("当前包为FU-B分片包\n");
- }
- }
- else
- {
- printf("这个包有错误,30-31 没有定义\n");
- }
- total_recved += total_bytes;
- printf("total_recved = %d\n",total_recved);
- memset(recvbuf,0,1500);
- free (p->payload);
- free (p);
- FreeNALU(n);
-
-
- return ;
- }
-
-
- int main()
- {
- char recvbuf[MAXDATASIZE];
- int sockfd;
- int client_fd;
- int sin_size;
- char sendbuf[BUFFER_SIZE];
- struct sockaddr_in server_sockaddr, client_sockaddr;
-
- int receive_bytes = 0;
-
- OpenBitstreamFile(outputfilename);
-
-
-
-
- if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
- {
- perror("socket");
- exit(1);
- }
- printf("create socket success!\n");
-
- server_sockaddr.sin_family = AF_INET;
- server_sockaddr.sin_addr.s_addr = INADDR_ANY;
- server_sockaddr.sin_port = htons(PORT);
- bzero(&(server_sockaddr.sin_zero), 8);
-
- if (bind(sockfd, (struct sockaddr *) &server_sockaddr,
- sizeof(struct sockaddr)) < 0)
- {
- perror("ERROR on binding");
- exit(1);
- }
- printf("bind success!\n");
-
- sin_size = sizeof(struct sockaddr_in);
- printf("waiting for client connection...\n");
-
- while((receive_bytes = recvfrom(sockfd, recvbuf, MAXDATASIZE, 0, (struct sockaddr *)&client_sockaddr, &sin_size)) >0)
- {
- if(strncmp(recvbuf, "over",4) == 0)
-
- {
-
- break;
-
- }
- poutfile = fopen(outputfilename,"ab+");
- rtp_unpackage(recvbuf,receive_bytes);
- fclose(poutfile);
- }
- strcpy(sendbuf, "success");
- sendto( sockfd, sendbuf, BUFFER_SIZE, 0 ,(struct sockaddr *)&client_sockaddr, sin_size);
- close(client_fd);
- close(sockfd);
- return 0;
- }
[cpp] view plain copy print ?
- #include <stdio.h>
-
- #include <stdlib.h>
-
- #include <string.h>
-
- #include <sys/socket.h>
-
- #include <netinet/in.h>
- #include <arpa/inet.h>
-
- #include <unistd.h>
-
- #include <errno.h>
-
- #include <sys/types.h>
-
- #include <fcntl.h>
-
- typedef struct
- {
- unsigned char version;
- unsigned char padding;
- unsigned char extension;
- unsigned char cc;
- unsigned char marker;
- unsigned char pt;
- unsigned int seq_no;
- unsigned int timestamp;
- unsigned int ssrc;
- unsigned char * payload;
- unsigned int paylen;
- } RTPpacket_t;
-
- typedef struct
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- unsigned char csrc_len:4;
- unsigned char extension:1;
- unsigned char padding:1;
- unsigned char version:2;
-
- unsigned char payloadtype:7;
- unsigned char marker:1;
-
- unsigned int seq_no;
-
- unsigned int timestamp;
-
- unsigned int ssrc;
- } RTP_FIXED_HEADER;
-
-
- typedef struct
- {
- unsigned char forbidden_bit;
- unsigned char nal_reference_idc;
- unsigned char nal_unit_type;
- unsigned int startcodeprefix_len;
- unsigned int len;
- unsigned int max_size;
- unsigned char * buf;
- unsigned int lost_packets;
- } NALU_t;
-
-
-
-
-
-
-
-
- typedef struct
- {
-
- unsigned char TYPE:5;
- unsigned char NRI:2;
- unsigned char F:1;
- } NALU_HEADER;
-
-
-
-
-
-
-
-
- typedef struct
- {
-
- unsigned char TYPE:5;
- unsigned char NRI:2;
- unsigned char F:1;
- } FU_INDICATOR;
-
-
-
-
-
-
-
-
- typedef struct
- {
-
- unsigned char TYPE:5;
- unsigned char R:1;
- unsigned char E:1;
- unsigned char S:1;
- } FU_HEADER;
-
- #define MAXDATASIZE 1500
- #define PORT 1234
- #define BUFFER_SIZE 10
-
- FILE * poutfile = NULL;
-
- char * outputfilename = "./receive.264";
-
- int OpenBitstreamFile (char *fn)
- {
- if (NULL == (poutfile = fopen(fn, "wb")))
- {
- printf("Error: Open input file error\n");
- getchar();
- }
- return 1;
- }
-
- NALU_t *AllocNALU(int buffersize)
- {
- NALU_t *n;
-
- if ((n = (NALU_t*)calloc (1, sizeof(NALU_t))) == NULL)
- {
- printf("AllocNALU Error: Allocate Meory To NALU_t Failed ");
- exit(0);
- }
- return n;
- }
-
- void FreeNALU(NALU_t *n)
- {
- if (n)
- {
- free (n);
- }
- }
-
-
-
-
-
- void rtp_unpackage(char *bufIn,int len)
- {
- unsigned char recvbuf[1500];
- RTPpacket_t *p = NULL;
- RTP_FIXED_HEADER * rtp_hdr = NULL;
- NALU_HEADER * nalu_hdr = NULL;
- NALU_t * n = NULL;
- FU_INDICATOR *fu_ind = NULL;
- FU_HEADER *fu_hdr= NULL;
- int total_bytes = 0;
- static int total_recved = 0;
- int fwrite_number = 0;
-
- memcpy(recvbuf,bufIn, len);
- printf("包长度+ rtp头: = %d\n",len);
-
-
-
-
- p = (RTPpacket_t*)&recvbuf[0];
- if ((p = malloc (sizeof (RTPpacket_t)))== NULL)
- {
- printf ("RTPpacket_t MMEMORY ERROR\n");
- }
- if ((p->payload = malloc (MAXDATASIZE))== NULL)
- {
- printf ("RTPpacket_t payload MMEMORY ERROR\n");
- }
-
- if ((rtp_hdr = malloc(sizeof(RTP_FIXED_HEADER))) == NULL)
- {
- printf("RTP_FIXED_HEADER MEMORY ERROR\n");
- }
-
- rtp_hdr =(RTP_FIXED_HEADER*)&recvbuf[0];
- printf("版本号 : %d\n",rtp_hdr->version);
- p->version = rtp_hdr->version;
- p->padding = rtp_hdr->padding;
- p->extension = rtp_hdr->extension;
- p->cc = rtp_hdr->csrc_len;
- printf("标志位 : %d\n",rtp_hdr->marker);
- p->marker = rtp_hdr->marker;
- printf("负载类型 :%d\n",rtp_hdr->payloadtype);
- p->pt = rtp_hdr->payloadtype;
- printf("包号 : %d \n",rtp_hdr->seq_no);
- p->seq_no = rtp_hdr->seq_no;
- printf("时间戳 : %d\n",rtp_hdr->timestamp);
- p->timestamp = rtp_hdr->timestamp;
- printf("帧号 : %d\n",rtp_hdr->ssrc);
- p->ssrc = rtp_hdr->ssrc;
-
-
-
-
- if (!(n = AllocNALU(800000)))
- {
- printf("NALU_t MMEMORY ERROR\n");
- }
- if ((nalu_hdr = malloc(sizeof(NALU_HEADER))) == NULL)
- {
- printf("NALU_HEADER MEMORY ERROR\n");
- }
-
- nalu_hdr =(NALU_HEADER*)&recvbuf[12];
- printf("forbidden_zero_bit: %d\n",nalu_hdr->F);
- n->forbidden_bit= nalu_hdr->F << 7;
- printf("nal_reference_idc: %d\n",nalu_hdr->NRI);
- n->nal_reference_idc = nalu_hdr->NRI << 5;
- printf("nal 负载类型: %d\n",nalu_hdr->TYPE);
- n->nal_unit_type = nalu_hdr->TYPE;
-
-
-
-
- if ( nalu_hdr->TYPE == 0)
- {
- printf("这个包有错误,0无定义\n");
- }
- else if ( nalu_hdr->TYPE >0 && nalu_hdr->TYPE < 24)
- {
- printf("当前包为单包\n");
- putc(0x00, poutfile);
- putc(0x00, poutfile);
- putc(0x00, poutfile);
- putc(0x01, poutfile);
- total_bytes +=4;
- memcpy(p->payload,&recvbuf[13],len-13);
- p->paylen = len-13;
- fwrite(nalu_hdr,1,1,poutfile);
- total_bytes += 1;
- fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);
- total_bytes = p->paylen;
- printf("包长度 + nal= %d\n",total_bytes);
- }
- else if ( nalu_hdr->TYPE == 24)
- {
- printf("当前包为STAP-A\n");
- }
- else if ( nalu_hdr->TYPE == 25)
- {
- printf("当前包为STAP-B\n");
- }
- else if (nalu_hdr->TYPE == 26)
- {
- printf("当前包为MTAP16\n");
- }
- else if ( nalu_hdr->TYPE == 27)
- {
- printf("当前包为MTAP24\n");
- }
- else if ( nalu_hdr->TYPE == 28)
- {
- if ((fu_ind = malloc(sizeof(FU_INDICATOR))) == NULL)
- {
- printf("FU_INDICATOR MEMORY ERROR\n");
- }
- if ((fu_hdr = malloc(sizeof(FU_HEADER))) == NULL)
- {
- printf("FU_HEADER MEMORY ERROR\n");
- }
-
- fu_ind=(FU_INDICATOR*)&recvbuf[12];
- printf("FU_INDICATOR->F :%d\n",fu_ind->F);
- n->forbidden_bit = fu_ind->F << 7;
- printf("FU_INDICATOR->NRI :%d\n",fu_ind->NRI);
- n->nal_reference_idc = fu_ind->NRI << 5;
- printf("FU_INDICATOR->TYPE :%d\n",fu_ind->TYPE);
- n->nal_unit_type = fu_ind->TYPE;
-
- fu_hdr=(FU_HEADER*)&recvbuf[13];
- printf("FU_HEADER->S :%d\n",fu_hdr->S);
- printf("FU_HEADER->E :%d\n",fu_hdr->E);
- printf("FU_HEADER->R :%d\n",fu_hdr->R);
- printf("FU_HEADER->TYPE :%d\n",fu_hdr->TYPE);
- n->nal_unit_type = fu_hdr->TYPE;
-
- if (rtp_hdr->marker == 1)
- {
- printf("当前包为FU-A分片包最后一个包\n");
- memcpy(p->payload,&recvbuf[14],len - 14);
- p->paylen = len - 14;
- fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);
- total_bytes = p->paylen;
- printf("包长度 + FU = %d\n",total_bytes);
- }
- else if (rtp_hdr->marker == 0)
- {
- if (fu_hdr->S == 1)
- {
- unsigned char F;
- unsigned char NRI;
- unsigned char TYPE;
- unsigned char nh;
- printf("当前包为FU-A分片包第一个包\n");
- putc(0x00, poutfile);
- putc(0x00, poutfile);
- putc(0x00, poutfile);
- putc(0x01, poutfile);
- total_bytes += 4;
-
- F = fu_ind->F << 7;
- NRI = fu_ind->NRI << 5;
- TYPE = fu_hdr->TYPE;
-
- nh = F | NRI | TYPE;
-
- putc(nh,poutfile);
-
- total_bytes +=1;
- memcpy(p->payload,&recvbuf[14],len - 14);
- p->paylen = len - 14;
- fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);
- total_bytes = p->paylen;
- printf("包长度 + FU_First = %d\n",total_bytes);
- }
- else
- {
- printf("当前包为FU-A分片包\n");
- memcpy(p->payload,&recvbuf[14],len - 14);
- p->paylen= len - 14;
- fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);
- total_bytes = p->paylen;
- printf("包长度 + FU = %d\n",total_bytes);
- }
- }
- }
- else if ( nalu_hdr->TYPE == 29)
- {
- if (rtp_hdr->marker == 1)
- {
- printf("当前包为FU-B分片包最后一个包\n");
-
- }
- else if (rtp_hdr->marker == 0)
- {
- printf("当前包为FU-B分片包\n");
- }
- }
- else
- {
- printf("这个包有错误,30-31 没有定义\n");
- }
- total_recved += total_bytes;
- printf("total_recved = %d\n",total_recved);
- memset(recvbuf,0,1500);
- free (p->payload);
- free (p);
- FreeNALU(n);
-
-
- return ;
- }
-
-
- int main()
- {
- char recvbuf[MAXDATASIZE];
- int sockfd;
- int client_fd;
- int sin_size;
- char sendbuf[BUFFER_SIZE];
- struct sockaddr_in server_sockaddr, client_sockaddr;
-
- int receive_bytes = 0;
-
- OpenBitstreamFile(outputfilename);
-
-
-
-
- if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
- {
- perror("socket");
- exit(1);
- }
- printf("create socket success!\n");
-
- server_sockaddr.sin_family = AF_INET;
- server_sockaddr.sin_addr.s_addr = INADDR_ANY;
- server_sockaddr.sin_port = htons(PORT);
- bzero(&(server_sockaddr.sin_zero), 8);
-
- if (bind(sockfd, (struct sockaddr *) &server_sockaddr,
- sizeof(struct sockaddr)) < 0)
- {
- perror("ERROR on binding");
- exit(1);
- }
- printf("bind success!\n");
-
- sin_size = sizeof(struct sockaddr_in);
- printf("waiting for client connection...\n");
-
- while((receive_bytes = recvfrom(sockfd, recvbuf, MAXDATASIZE, 0, (struct sockaddr *)&client_sockaddr, &sin_size)) >0)
- {
- if(strncmp(recvbuf, "over",4) == 0)
-
- {
-
- break;
-
- }
- poutfile = fopen(outputfilename,"ab+");
- rtp_unpackage(recvbuf,receive_bytes);
- fclose(poutfile);
- }
- strcpy(sendbuf, "success");
- sendto( sockfd, sendbuf, BUFFER_SIZE, 0 ,(struct sockaddr *)&client_sockaddr, sin_size);
- close(client_fd);
- close(sockfd);
- return 0;
- }
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>
typedef struct
{
unsigned char version; //!< Version, 2 bits, MUST be 0x2
unsigned char padding; //!< Padding bit, Padding MUST NOT be used
unsigned char extension; //!< Extension, MUST be zero
unsigned char cc; //!< CSRC count, normally 0 in the absence of RTP mixers
unsigned char marker; //!< Marker bit
unsigned char pt; //!< 7 bits, Payload Type, dynamically established
unsigned int seq_no; //!< RTP sequence number, incremented by one for each sent packet
unsigned int timestamp; //!< timestamp, 27 MHz for H.264
unsigned int ssrc; //!< Synchronization Source, chosen randomly
unsigned char * payload; //!< the payload including payload headers
unsigned int paylen; //!< length of payload in bytes
} RTPpacket_t;
typedef struct
{
/* 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X| CC |M| PT | sequence number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| synchronization source (SSRC) identifier |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| contributing source (CSRC) identifiers |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
//intel 的cpu 是intel为小端字节序(低端存到底地址) 而网络流为大端字节序(高端存到低地址)
/*intel 的cpu : 高端->csrc_len:4 -> extension:1-> padding:1 -> version:2 ->低端
在内存中存储 :
低->4001(内存地址)version:2
4002(内存地址)padding:1
4003(内存地址)extension:1
高->4004(内存地址)csrc_len:4
网络传输解析 : 高端->version:2->padding:1->extension:1->csrc_len:4->低端 (为正确的文档描述格式)
存入接收内存 :
低->4001(内存地址)version:2
4002(内存地址)padding:1
4003(内存地址)extension:1
高->4004(内存地址)csrc_len:4
本地内存解析 :高端->csrc_len:4 -> extension:1-> padding:1 -> version:2 ->低端 ,
即:
unsigned char csrc_len:4; // expect 0
unsigned char extension:1; // expect 1
unsigned char padding:1; // expect 0
unsigned char version:2; // expect 2
*/
/* byte 0 */
unsigned char csrc_len:4; /* expect 0 */
unsigned char extension:1; /* expect 1, see RTP_OP below */
unsigned char padding:1; /* expect 0 */
unsigned char version:2; /* expect 2 */
/* byte 1 */
unsigned char payloadtype:7; /* RTP_PAYLOAD_RTSP */
unsigned char marker:1; /* expect 1 */
/* bytes 2,3 */
unsigned int seq_no;
/* bytes 4-7 */
unsigned int timestamp;
/* bytes 8-11 */
unsigned int ssrc; /* stream number is used here. */
} RTP_FIXED_HEADER;
typedef struct
{
unsigned char forbidden_bit; //! Should always be FALSE
unsigned char nal_reference_idc; //! NALU_PRIORITY_xxxx
unsigned char nal_unit_type; //! NALU_TYPE_xxxx
unsigned int startcodeprefix_len; //! 前缀字节数
unsigned int len; //! 包含nal 头的nal 长度,从第一个00000001到下一个000000001的长度
unsigned int max_size; //! 做多一个nal 的长度
unsigned char * buf; //! 包含nal 头的nal 数据
unsigned int lost_packets; //! 预留
} NALU_t;
/*
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
*/
typedef struct
{
//byte 0
unsigned char TYPE:5;
unsigned char NRI:2;
unsigned char F:1;
} NALU_HEADER; // 1 BYTE
/*
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
*/
typedef struct
{
//byte 0
unsigned char TYPE:5;
unsigned char NRI:2;
unsigned char F:1;
} FU_INDICATOR; // 1 BYTE
/*
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E|R| Type |
+---------------+
*/
typedef struct
{
//byte 0
unsigned char TYPE:5;
unsigned char R:1;
unsigned char E:1;
unsigned char S:1;
} FU_HEADER; // 1 BYTES
#define MAXDATASIZE 1500
#define PORT 1234
#define BUFFER_SIZE 10
FILE * poutfile = NULL;
char * outputfilename = "./receive.264";
int OpenBitstreamFile (char *fn)
{
if (NULL == (poutfile = fopen(fn, "wb")))
{
printf("Error: Open input file error\n");
getchar();
}
return 1;
}
NALU_t *AllocNALU(int buffersize)
{
NALU_t *n;
if ((n = (NALU_t*)calloc (1, sizeof(NALU_t))) == NULL)
{
printf("AllocNALU Error: Allocate Meory To NALU_t Failed ");
exit(0);
}
return n;
}
void FreeNALU(NALU_t *n)
{
if (n)
{
free (n);
}
}
/*
*bufIn:rtppackage
*len: the lengthe of rtppackage
*/
void rtp_unpackage(char *bufIn,int len)
{
unsigned char recvbuf[1500];
RTPpacket_t *p = NULL;
RTP_FIXED_HEADER * rtp_hdr = NULL;
NALU_HEADER * nalu_hdr = NULL;
NALU_t * n = NULL;
FU_INDICATOR *fu_ind = NULL;
FU_HEADER *fu_hdr= NULL;
int total_bytes = 0; //当前包传出的数据
static int total_recved = 0; //一共传输的数据
int fwrite_number = 0; //存入文件的数据长度
memcpy(recvbuf,bufIn, len); //复制rtp包
printf("包长度+ rtp头: = %d\n",len);
//////////////////////////////////////////////////////////////////////////
//begin rtp_payload and rtp_header
p = (RTPpacket_t*)&recvbuf[0];
if ((p = malloc (sizeof (RTPpacket_t)))== NULL)
{
printf ("RTPpacket_t MMEMORY ERROR\n");
}
if ((p->payload = malloc (MAXDATASIZE))== NULL)
{
printf ("RTPpacket_t payload MMEMORY ERROR\n");
}
if ((rtp_hdr = malloc(sizeof(RTP_FIXED_HEADER))) == NULL)
{
printf("RTP_FIXED_HEADER MEMORY ERROR\n");
}
rtp_hdr =(RTP_FIXED_HEADER*)&recvbuf[0];
printf("版本号 : %d\n",rtp_hdr->version);
p->version = rtp_hdr->version;
p->padding = rtp_hdr->padding;
p->extension = rtp_hdr->extension;
p->cc = rtp_hdr->csrc_len;
printf("标志位 : %d\n",rtp_hdr->marker);
p->marker = rtp_hdr->marker;
printf("负载类型 :%d\n",rtp_hdr->payloadtype);
p->pt = rtp_hdr->payloadtype;
printf("包号 : %d \n",rtp_hdr->seq_no);
p->seq_no = rtp_hdr->seq_no;
printf("时间戳 : %d\n",rtp_hdr->timestamp);
p->timestamp = rtp_hdr->timestamp;
printf("帧号 : %d\n",rtp_hdr->ssrc);
p->ssrc = rtp_hdr->ssrc;
//end rtp_payload and rtp_header
//////////////////////////////////////////////////////////////////////////
//begin nal_hdr
if (!(n = AllocNALU(800000))) //为结构体nalu_t及其成员buf分配空间。返回值为指向nalu_t存储空间的指针
{
printf("NALU_t MMEMORY ERROR\n");
}
if ((nalu_hdr = malloc(sizeof(NALU_HEADER))) == NULL)
{
printf("NALU_HEADER MEMORY ERROR\n");
}
nalu_hdr =(NALU_HEADER*)&recvbuf[12]; //网络传输过来的字节序 ,当存入内存还是和文档描述的相反,只要匹配网络字节序和文档描述即可传输正确。
printf("forbidden_zero_bit: %d\n",nalu_hdr->F); //网络传输中的方式为:F->NRI->TYPE.. 内存中存储方式为 TYPE->NRI->F (和nal头匹配)。
n->forbidden_bit= nalu_hdr->F << 7; //内存中的字节序。
printf("nal_reference_idc: %d\n",nalu_hdr->NRI);
n->nal_reference_idc = nalu_hdr->NRI << 5;
printf("nal 负载类型: %d\n",nalu_hdr->TYPE);
n->nal_unit_type = nalu_hdr->TYPE;
//end nal_hdr
//////////////////////////////////////////////////////////////////////////
//开始解包
if ( nalu_hdr->TYPE == 0)
{
printf("这个包有错误,0无定义\n");
}
else if ( nalu_hdr->TYPE >0 && nalu_hdr->TYPE < 24) //单包
{
printf("当前包为单包\n");
putc(0x00, poutfile);
putc(0x00, poutfile);
putc(0x00, poutfile);
putc(0x01, poutfile); //写进起始字节0x00000001
total_bytes +=4;
memcpy(p->payload,&recvbuf[13],len-13);
p->paylen = len-13;
fwrite(nalu_hdr,1,1,poutfile); //写NAL_HEADER
total_bytes += 1;
fwrite_number = fwrite(p->payload,1,p->paylen,poutfile); //写NAL数据
total_bytes = p->paylen;
printf("包长度 + nal= %d\n",total_bytes);
}
else if ( nalu_hdr->TYPE == 24) //STAP-A 单一时间的组合包
{
printf("当前包为STAP-A\n");
}
else if ( nalu_hdr->TYPE == 25) //STAP-B 单一时间的组合包
{
printf("当前包为STAP-B\n");
}
else if (nalu_hdr->TYPE == 26) //MTAP16 多个时间的组合包
{
printf("当前包为MTAP16\n");
}
else if ( nalu_hdr->TYPE == 27) //MTAP24 多个时间的组合包
{
printf("当前包为MTAP24\n");
}
else if ( nalu_hdr->TYPE == 28) //FU-A分片包,解码顺序和传输顺序相同
{
if ((fu_ind = malloc(sizeof(FU_INDICATOR))) == NULL)
{
printf("FU_INDICATOR MEMORY ERROR\n");
}
if ((fu_hdr = malloc(sizeof(FU_HEADER))) == NULL)
{
printf("FU_HEADER MEMORY ERROR\n");
}
fu_ind=(FU_INDICATOR*)&recvbuf[12]; //分片包用的是FU_INDICATOR而不是NALU_HEADER
printf("FU_INDICATOR->F :%d\n",fu_ind->F);
n->forbidden_bit = fu_ind->F << 7;
printf("FU_INDICATOR->NRI :%d\n",fu_ind->NRI);
n->nal_reference_idc = fu_ind->NRI << 5;
printf("FU_INDICATOR->TYPE :%d\n",fu_ind->TYPE);
n->nal_unit_type = fu_ind->TYPE;
fu_hdr=(FU_HEADER*)&recvbuf[13]; //FU_HEADER赋值
printf("FU_HEADER->S :%d\n",fu_hdr->S);
printf("FU_HEADER->E :%d\n",fu_hdr->E);
printf("FU_HEADER->R :%d\n",fu_hdr->R);
printf("FU_HEADER->TYPE :%d\n",fu_hdr->TYPE);
n->nal_unit_type = fu_hdr->TYPE; //应用的是FU_HEADER的TYPE
if (rtp_hdr->marker == 1) //分片包最后一个包
{
printf("当前包为FU-A分片包最后一个包\n");
memcpy(p->payload,&recvbuf[14],len - 14);
p->paylen = len - 14;
fwrite_number = fwrite(p->payload,1,p->paylen,poutfile); //写NAL数据
total_bytes = p->paylen;
printf("包长度 + FU = %d\n",total_bytes);
}
else if (rtp_hdr->marker == 0) //分片包 但不是最后一个包
{
if (fu_hdr->S == 1) //分片的第一个包
{
unsigned char F;
unsigned char NRI;
unsigned char TYPE;
unsigned char nh;
printf("当前包为FU-A分片包第一个包\n");
putc(0x00, poutfile);
putc(0x00, poutfile);
putc(0x00, poutfile);
putc(0x01, poutfile); //写起始字节码0x00000001
total_bytes += 4;
F = fu_ind->F << 7;
NRI = fu_ind->NRI << 5;
TYPE = fu_hdr->TYPE; //应用的是FU_HEADER的TYPE
//nh = n->forbidden_bit|n->nal_reference_idc|n->nal_unit_type; //二进制文件也是按 大字节序存储
nh = F | NRI | TYPE;
putc(nh,poutfile); //写NAL HEADER
total_bytes +=1;
memcpy(p->payload,&recvbuf[14],len - 14);
p->paylen = len - 14;
fwrite_number = fwrite(p->payload,1,p->paylen,poutfile); //写NAL数据
total_bytes = p->paylen;
printf("包长度 + FU_First = %d\n",total_bytes);
}
else //如果不是第一个包
{
printf("当前包为FU-A分片包\n");
memcpy(p->payload,&recvbuf[14],len - 14);
p->paylen= len - 14;
fwrite_number = fwrite(p->payload,1,p->paylen,poutfile); //写NAL数据
total_bytes = p->paylen;
printf("包长度 + FU = %d\n",total_bytes);
}
}
}
else if ( nalu_hdr->TYPE == 29) //FU-B分片包,解码顺序和传输顺序相同
{
if (rtp_hdr->marker == 1) //分片包最后一个包
{
printf("当前包为FU-B分片包最后一个包\n");
}
else if (rtp_hdr->marker == 0) //分片包 但不是最后一个包
{
printf("当前包为FU-B分片包\n");
}
}
else
{
printf("这个包有错误,30-31 没有定义\n");
}
total_recved += total_bytes;
printf("total_recved = %d\n",total_recved);
memset(recvbuf,0,1500);
free (p->payload);
free (p);
FreeNALU(n);
//结束解包
//////////////////////////////////////////////////////////////////////////
return ;
}
int main()
{
char recvbuf[MAXDATASIZE]; //加上头最大传输数据 1500
int sockfd;
int client_fd;
int sin_size;
char sendbuf[BUFFER_SIZE];
struct sockaddr_in server_sockaddr, client_sockaddr;
int receive_bytes = 0;
OpenBitstreamFile(outputfilename);
//////////////////////////////////////////////////////////////////////////
//socket 操作
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("socket");
exit(1);
}//建立socket链接,数据报socket,IPv4协议
printf("create socket success!\n");
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_addr.s_addr = INADDR_ANY;//0.0.0.0不确定地址
server_sockaddr.sin_port = htons(PORT);
bzero(&(server_sockaddr.sin_zero), 8); //填充0以保持与struct sockaddr同样大小
if (bind(sockfd, (struct sockaddr *) &server_sockaddr,
sizeof(struct sockaddr)) < 0)
{
perror("ERROR on binding");
exit(1);
}
printf("bind success!\n");
sin_size = sizeof(struct sockaddr_in);
printf("waiting for client connection...\n");
//接收从客户端发来的数据
while((receive_bytes = recvfrom(sockfd, recvbuf, MAXDATASIZE, 0, (struct sockaddr *)&client_sockaddr, &sin_size)) >0)
{
if(strncmp(recvbuf, "over",4) == 0)
{
break;
}
poutfile = fopen(outputfilename,"ab+");
rtp_unpackage(recvbuf,receive_bytes);
fclose(poutfile);
}
strcpy(sendbuf, "success");
sendto( sockfd, sendbuf, BUFFER_SIZE, 0 ,(struct sockaddr *)&client_sockaddr, sin_size);
close(client_fd);
close(sockfd);
return 0;
}
因为这里用的是recvfrom,因此将上一篇的打包发送中socket的send修改成sendto即可。还有一点是udp发送的速度很快,这里因为要将数据写进文件中,速度肯定没有接受数据快,因此在打包发送端每发送完一个rtp数据包延迟一段时间才行,这里我延时了10ms。