同前篇类似,修改自vc下的程序,跟打包相反,原理就是从udp接收一个数据包,判断这个数据包是单个发送还是分片发送,进而获取rtp包中的h264NAL数据,并加上0x00000001起始字节一并写进文件中即可。
- #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;
- }
- #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;
- }
#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。