H.264 RTP解码

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

  1. #include <stdio.h>  
  2.   
  3. #include <stdlib.h>  
  4.   
  5. #include <string.h>  
  6.   
  7. #include <sys/socket.h>  
  8.   
  9. #include <netinet/in.h>  
  10. #include <arpa/inet.h>  
  11.   
  12. #include <unistd.h>  
  13.   
  14. #include <errno.h>  
  15.   
  16. #include <sys/types.h>  
  17.   
  18. #include <fcntl.h>  
  19.   
  20. typedef struct  
  21. {  
  22.     unsigned char version;              //!< Version, 2 bits, MUST be 0x2  
  23.     unsigned char padding;              //!< Padding bit, Padding MUST NOT be used  
  24.     unsigned char extension;            //!< Extension, MUST be zero  
  25.     unsigned char cc;                   //!< CSRC count, normally 0 in the absence of RTP mixers           
  26.     unsigned char marker;               //!< Marker bit  
  27.     unsigned char pt;                   //!< 7 bits, Payload Type, dynamically established  
  28.     unsigned int seq_no;                //!< RTP sequence number, incremented by one for each sent packet   
  29.     unsigned int timestamp;        //!< timestamp, 27 MHz for H.264  
  30.     unsigned int ssrc;             //!< Synchronization Source, chosen randomly  
  31.     unsigned char * payload;      //!< the payload including payload headers  
  32.     unsigned int paylen;           //!< length of payload in bytes  
  33. } RTPpacket_t;  
  34.   
  35. typedef struct   
  36. {  
  37.     /*  0                   1                   2                   3 
  38.     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 
  39.     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
  40.     |V=2|P|X|  CC   |M|     PT      |       sequence number         | 
  41.     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
  42.     |                           timestamp                           | 
  43.     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
  44.     |           synchronization source (SSRC) identifier            | 
  45.     +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 
  46.     |            contributing source (CSRC) identifiers             | 
  47.     |                             ....                              | 
  48.     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
  49.     */  
  50.     //intel 的cpu 是intel为小端字节序(低端存到底地址) 而网络流为大端字节序(高端存到低地址)  
  51.     /*intel 的cpu : 高端->csrc_len:4 -> extension:1-> padding:1 -> version:2 ->低端 
  52.      在内存中存储 : 
  53.      低->4001(内存地址)version:2 
  54.          4002(内存地址)padding:1 
  55.          4003(内存地址)extension:1 
  56.      高->4004(内存地址)csrc_len:4 
  57.  
  58.      网络传输解析 : 高端->version:2->padding:1->extension:1->csrc_len:4->低端  (为正确的文档描述格式) 
  59.  
  60.      存入接收内存 : 
  61.      低->4001(内存地址)version:2 
  62.          4002(内存地址)padding:1 
  63.          4003(内存地址)extension:1 
  64.      高->4004(内存地址)csrc_len:4 
  65.      本地内存解析 :高端->csrc_len:4 -> extension:1-> padding:1 -> version:2 ->低端 , 
  66.      即: 
  67.      unsigned char csrc_len:4;        // expect 0  
  68.      unsigned char extension:1;       // expect 1 
  69.      unsigned char padding:1;         // expect 0  
  70.      unsigned char version:2;         // expect 2  
  71.     */  
  72.     /* byte 0 */  
  73.      unsigned char csrc_len:4;        /* expect 0 */  
  74.      unsigned char extension:1;       /* expect 1, see RTP_OP below */  
  75.      unsigned char padding:1;         /* expect 0 */  
  76.      unsigned char version:2;         /* expect 2 */  
  77.     /* byte 1 */  
  78.      unsigned char payloadtype:7;     /* RTP_PAYLOAD_RTSP */  
  79.      unsigned char marker:1;          /* expect 1 */  
  80.     /* bytes 2,3 */  
  81.      unsigned int seq_no;              
  82.     /* bytes 4-7 */  
  83.      unsigned int timestamp;          
  84.     /* bytes 8-11 */  
  85.      unsigned int ssrc;              /* stream number is used here. */  
  86. } RTP_FIXED_HEADER;  
  87.   
  88.   
  89. typedef struct  
  90. {  
  91.     unsigned char forbidden_bit;           //! Should always be FALSE  
  92.     unsigned char nal_reference_idc;       //! NALU_PRIORITY_xxxx  
  93.     unsigned char nal_unit_type;           //! NALU_TYPE_xxxx    
  94.     unsigned int startcodeprefix_len;      //! 前缀字节数  
  95.     unsigned int len;                      //! 包含nal 头的nal 长度,从第一个00000001到下一个000000001的长度  
  96.     unsigned int max_size;                 //! 做多一个nal 的长度  
  97.     unsigned char * buf;                   //! 包含nal 头的nal 数据  
  98.     unsigned int lost_packets;             //! 预留  
  99. } NALU_t;  
  100.   
  101. /* 
  102. +---------------+ 
  103. |0|1|2|3|4|5|6|7| 
  104. +-+-+-+-+-+-+-+-+ 
  105. |F|NRI|  Type   | 
  106. +---------------+ 
  107. */  
  108. typedef struct   
  109. {  
  110.     //byte 0  
  111.     unsigned char TYPE:5;  
  112.     unsigned char NRI:2;  
  113.     unsigned char F:1;          
  114. } NALU_HEADER; // 1 BYTE   
  115.   
  116. /* 
  117. +---------------+ 
  118. |0|1|2|3|4|5|6|7| 
  119. +-+-+-+-+-+-+-+-+ 
  120. |F|NRI|  Type   | 
  121. +---------------+ 
  122. */  
  123. typedef struct   
  124. {  
  125.     //byte 0  
  126.     unsigned char TYPE:5;  
  127.     unsigned char NRI:2;   
  128.     unsigned char F:1;                
  129. } FU_INDICATOR; // 1 BYTE   
  130.   
  131. /* 
  132. +---------------+ 
  133. |0|1|2|3|4|5|6|7| 
  134. +-+-+-+-+-+-+-+-+ 
  135. |S|E|R|  Type   | 
  136. +---------------+ 
  137. */  
  138. typedef struct   
  139. {  
  140.     //byte 0  
  141.     unsigned char TYPE:5;  
  142.     unsigned char R:1;  
  143.     unsigned char E:1;  
  144.     unsigned char S:1;      
  145. } FU_HEADER;   // 1 BYTES   
  146.   
  147. #define  MAXDATASIZE 1500  
  148. #define PORT    1234  
  149. #define BUFFER_SIZE 10  
  150.   
  151. FILE * poutfile =  NULL;      
  152.   
  153. char * outputfilename = "./receive.264";  
  154.   
  155. int  OpenBitstreamFile (char *fn)  
  156. {  
  157.     if (NULL == (poutfile = fopen(fn, "wb")))  
  158.     {  
  159.         printf("Error: Open input file error\n");  
  160.         getchar();  
  161.     }  
  162.     return 1;  
  163. }  
  164.   
  165. NALU_t *AllocNALU(int buffersize)  
  166. {  
  167.     NALU_t *n;  
  168.   
  169.     if ((n = (NALU_t*)calloc (1, sizeof(NALU_t))) == NULL)  
  170.     {  
  171.         printf("AllocNALU Error: Allocate Meory To NALU_t Failed ");  
  172.         exit(0);  
  173.     }  
  174.     return n;  
  175. }  
  176.   
  177. void FreeNALU(NALU_t *n)  
  178. {  
  179.     if (n)  
  180.     {  
  181.         free (n);  
  182.     }  
  183. }  
  184.   
  185. /* 
  186. *bufIn:rtppackage 
  187. *len: the lengthe of rtppackage 
  188. */  
  189. void rtp_unpackage(char *bufIn,int len)  
  190. {  
  191.     unsigned char recvbuf[1500];  
  192.     RTPpacket_t *p = NULL;   
  193.     RTP_FIXED_HEADER * rtp_hdr = NULL;  
  194.     NALU_HEADER * nalu_hdr = NULL;  
  195.     NALU_t * n  = NULL;  
  196.     FU_INDICATOR    *fu_ind = NULL;  
  197.     FU_HEADER       *fu_hdr= NULL;  
  198.     int total_bytes = 0;                 //当前包传出的数据  
  199.     static int total_recved = 0;         //一共传输的数据  
  200.     int fwrite_number = 0;               //存入文件的数据长度  
  201.   
  202.     memcpy(recvbuf,bufIn, len);          //复制rtp包   
  203.     printf("包长度+ rtp头:   = %d\n",len);  
  204.   
  205.     //  
  206.     //begin rtp_payload and rtp_header  
  207.   
  208.     p = (RTPpacket_t*)&recvbuf[0];  
  209.     if ((p = malloc (sizeof (RTPpacket_t)))== NULL)  
  210.     {  
  211.         printf ("RTPpacket_t MMEMORY ERROR\n");  
  212.     }  
  213.     if ((p->payload = malloc (MAXDATASIZE))== NULL)  
  214.     {  
  215.         printf ("RTPpacket_t payload MMEMORY ERROR\n");  
  216.     }  
  217.   
  218.     if ((rtp_hdr = malloc(sizeof(RTP_FIXED_HEADER))) == NULL)  
  219.     {  
  220.         printf("RTP_FIXED_HEADER MEMORY ERROR\n");  
  221.     }  
  222.       
  223.     rtp_hdr =(RTP_FIXED_HEADER*)&recvbuf[0];   
  224.     printf("版本号     : %d\n",rtp_hdr->version);  
  225.     p->version  = rtp_hdr->version;  
  226.     p->padding  = rtp_hdr->padding;  
  227.     p->extension  = rtp_hdr->extension;  
  228.     p->cc = rtp_hdr->csrc_len;  
  229.     printf("标志位     : %d\n",rtp_hdr->marker);  
  230.     p->marker = rtp_hdr->marker;  
  231.     printf("负载类型    :%d\n",rtp_hdr->payloadtype);  
  232.     p->pt = rtp_hdr->payloadtype;  
  233.     printf("包号      : %d \n",rtp_hdr->seq_no);  
  234.     p->seq_no = rtp_hdr->seq_no;  
  235.     printf("时间戳     : %d\n",rtp_hdr->timestamp);  
  236.     p->timestamp = rtp_hdr->timestamp;  
  237.     printf("帧号      : %d\n",rtp_hdr->ssrc);  
  238.     p->ssrc = rtp_hdr->ssrc;  
  239.       
  240.     //end rtp_payload and rtp_header  
  241.     //  
  242.     //begin nal_hdr  
  243.     if (!(n = AllocNALU(800000)))          //为结构体nalu_t及其成员buf分配空间。返回值为指向nalu_t存储空间的指针  
  244.     {  
  245.         printf("NALU_t MMEMORY ERROR\n");  
  246.     }  
  247.     if ((nalu_hdr = malloc(sizeof(NALU_HEADER))) == NULL)  
  248.     {  
  249.         printf("NALU_HEADER MEMORY ERROR\n");  
  250.     }  
  251.   
  252.     nalu_hdr =(NALU_HEADER*)&recvbuf[12];                        //网络传输过来的字节序 ,当存入内存还是和文档描述的相反,只要匹配网络字节序和文档描述即可传输正确。  
  253.     printf("forbidden_zero_bit: %d\n",nalu_hdr->F);              //网络传输中的方式为:F->NRI->TYPE.. 内存中存储方式为 TYPE->NRI->F (和nal头匹配)。  
  254.     n->forbidden_bit= nalu_hdr->F << 7;                          //内存中的字节序。  
  255.     printf("nal_reference_idc:  %d\n",nalu_hdr->NRI);  
  256.     n->nal_reference_idc = nalu_hdr->NRI << 5;                        
  257.     printf("nal 负载类型:       %d\n",nalu_hdr->TYPE);  
  258.     n->nal_unit_type = nalu_hdr->TYPE;  
  259.   
  260.     //end nal_hdr  
  261.     //  
  262.     //开始解包  
  263.     if ( nalu_hdr->TYPE  == 0)  
  264.     {  
  265.         printf("这个包有错误,0无定义\n");  
  266.     }  
  267.     else if ( nalu_hdr->TYPE >0 &&  nalu_hdr->TYPE < 24)  //单包  
  268.     {  
  269.         printf("当前包为单包\n");  
  270.         putc(0x00, poutfile);  
  271.         putc(0x00, poutfile);  
  272.         putc(0x00, poutfile);  
  273.         putc(0x01, poutfile);   //写进起始字节0x00000001  
  274.         total_bytes +=4;  
  275.         memcpy(p->payload,&recvbuf[13],len-13);    
  276.         p->paylen = len-13;  
  277.         fwrite(nalu_hdr,1,1,poutfile);  //写NAL_HEADER  
  278.         total_bytes += 1;  
  279.         fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);  //写NAL数据  
  280.         total_bytes = p->paylen;  
  281.         printf("包长度 + nal= %d\n",total_bytes);  
  282.     }  
  283.     else if ( nalu_hdr->TYPE == 24)                    //STAP-A   单一时间的组合包  
  284.     {  
  285.         printf("当前包为STAP-A\n");  
  286.     }  
  287.     else if ( nalu_hdr->TYPE == 25)                    //STAP-B   单一时间的组合包  
  288.     {  
  289.         printf("当前包为STAP-B\n");  
  290.     }  
  291.     else if (nalu_hdr->TYPE == 26)                     //MTAP16   多个时间的组合包  
  292.     {  
  293.         printf("当前包为MTAP16\n");  
  294.     }  
  295.     else if ( nalu_hdr->TYPE == 27)                    //MTAP24   多个时间的组合包  
  296.     {  
  297.         printf("当前包为MTAP24\n");  
  298.     }  
  299.      else if ( nalu_hdr->TYPE == 28)                    //FU-A分片包,解码顺序和传输顺序相同  
  300.     {  
  301.         if ((fu_ind = malloc(sizeof(FU_INDICATOR))) == NULL)  
  302.         {  
  303.             printf("FU_INDICATOR MEMORY ERROR\n");  
  304.         }  
  305.         if ((fu_hdr = malloc(sizeof(FU_HEADER))) == NULL)  
  306.         {  
  307.             printf("FU_HEADER MEMORY ERROR\n");  
  308.         }  
  309.   
  310.         fu_ind=(FU_INDICATOR*)&recvbuf[12];     //分片包用的是FU_INDICATOR而不是NALU_HEADER  
  311.         printf("FU_INDICATOR->F     :%d\n",fu_ind->F);  
  312.         n->forbidden_bit = fu_ind->F << 7;  
  313.         printf("FU_INDICATOR->NRI   :%d\n",fu_ind->NRI);  
  314.         n->nal_reference_idc = fu_ind->NRI << 5;                        
  315.         printf("FU_INDICATOR->TYPE  :%d\n",fu_ind->TYPE);  
  316.         n->nal_unit_type = fu_ind->TYPE;  
  317.   
  318.         fu_hdr=(FU_HEADER*)&recvbuf[13];        //FU_HEADER赋值  
  319.         printf("FU_HEADER->S        :%d\n",fu_hdr->S);  
  320.         printf("FU_HEADER->E        :%d\n",fu_hdr->E);  
  321.         printf("FU_HEADER->R        :%d\n",fu_hdr->R);  
  322.         printf("FU_HEADER->TYPE     :%d\n",fu_hdr->TYPE);  
  323.         n->nal_unit_type = fu_hdr->TYPE;               //应用的是FU_HEADER的TYPE  
  324.   
  325.         if (rtp_hdr->marker == 1)                      //分片包最后一个包  
  326.         {  
  327.             printf("当前包为FU-A分片包最后一个包\n");  
  328.             memcpy(p->payload,&recvbuf[14],len - 14);  
  329.             p->paylen = len - 14;  
  330.             fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);  //写NAL数据  
  331.             total_bytes = p->paylen;  
  332.             printf("包长度 + FU = %d\n",total_bytes);    
  333.         }  
  334.         else if (rtp_hdr->marker == 0)                 //分片包 但不是最后一个包  
  335.         {  
  336.             if (fu_hdr->S == 1)                        //分片的第一个包  
  337.             {  
  338.                 unsigned char F;  
  339.                 unsigned char NRI;  
  340.                 unsigned char TYPE;  
  341.                 unsigned char nh;  
  342.                 printf("当前包为FU-A分片包第一个包\n");  
  343.                 putc(0x00, poutfile);  
  344.                 putc(0x00, poutfile);  
  345.                 putc(0x00, poutfile);  
  346.                 putc(0x01, poutfile);               //写起始字节码0x00000001  
  347.                 total_bytes += 4;  
  348.                   
  349.                 F = fu_ind->F << 7;  
  350.                 NRI = fu_ind->NRI << 5;  
  351.                 TYPE = fu_hdr->TYPE;                                            //应用的是FU_HEADER的TYPE  
  352.                 //nh = n->forbidden_bit|n->nal_reference_idc|n->nal_unit_type;  //二进制文件也是按 大字节序存储  
  353.                 nh = F | NRI | TYPE;  
  354.   
  355.                 putc(nh,poutfile);              //写NAL HEADER  
  356.   
  357.                 total_bytes +=1;  
  358.                 memcpy(p->payload,&recvbuf[14],len - 14);  
  359.                 p->paylen = len - 14;  
  360.                 fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);  //写NAL数据  
  361.                 total_bytes = p->paylen;  
  362.                 printf("包长度 + FU_First = %d\n",total_bytes);      
  363.             }  
  364.             else                                      //如果不是第一个包  
  365.             {  
  366.                 printf("当前包为FU-A分片包\n");  
  367.                 memcpy(p->payload,&recvbuf[14],len - 14);  
  368.                 p->paylen= len - 14;  
  369.                 fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);  //写NAL数据  
  370.                 total_bytes = p->paylen;  
  371.                 printf("包长度 + FU = %d\n",total_bytes);    
  372.             }     
  373.         }  
  374.     }  
  375.     else if ( nalu_hdr->TYPE == 29)                //FU-B分片包,解码顺序和传输顺序相同  
  376.     {  
  377.         if (rtp_hdr->marker == 1)                  //分片包最后一个包  
  378.         {  
  379.             printf("当前包为FU-B分片包最后一个包\n");  
  380.   
  381.         }  
  382.         else if (rtp_hdr->marker == 0)             //分片包 但不是最后一个包  
  383.         {  
  384.             printf("当前包为FU-B分片包\n");  
  385.         }  
  386.     }  
  387.     else  
  388.     {  
  389.         printf("这个包有错误,30-31 没有定义\n");  
  390.     }  
  391.     total_recved += total_bytes;  
  392.     printf("total_recved = %d\n",total_recved);  
  393.     memset(recvbuf,0,1500);  
  394.     free (p->payload);  
  395.     free (p);  
  396.     FreeNALU(n);  
  397.     //结束解包  
  398.     //  
  399.     return ;  
  400. }  
  401.   
  402.   
  403. int main()  
  404. {  
  405.     char recvbuf[MAXDATASIZE];  //加上头最大传输数据 1500  
  406.     int sockfd;    
  407.     int client_fd;    
  408.     int sin_size;    
  409.     char sendbuf[BUFFER_SIZE];  
  410.     struct sockaddr_in server_sockaddr, client_sockaddr;    
  411.   
  412.     int receive_bytes = 0;  
  413.   
  414.     OpenBitstreamFile(outputfilename);   
  415.       
  416.     //  
  417.     //socket 操作  
  418.       
  419.     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)  
  420.     {  
  421.         perror("socket");  
  422.         exit(1);  
  423.     }//建立socket链接,数据报socket,IPv4协议  
  424.     printf("create socket success!\n");  
  425.   
  426.     server_sockaddr.sin_family = AF_INET;    
  427.     server_sockaddr.sin_addr.s_addr = INADDR_ANY;//0.0.0.0不确定地址    
  428.     server_sockaddr.sin_port = htons(PORT);    
  429.     bzero(&(server_sockaddr.sin_zero), 8);  //填充0以保持与struct sockaddr同样大小  
  430.   
  431.     if (bind(sockfd, (struct sockaddr *) &server_sockaddr,    
  432.           sizeof(struct sockaddr)) < 0)     
  433.     {  
  434.         perror("ERROR on binding");  
  435.         exit(1);   
  436.     }   
  437.     printf("bind success!\n");  
  438.   
  439.     sin_size = sizeof(struct sockaddr_in);  
  440.     printf("waiting for client connection...\n");  
  441.     //接收从客户端发来的数据  
  442.     while((receive_bytes = recvfrom(sockfd, recvbuf, MAXDATASIZE, 0, (struct sockaddr *)&client_sockaddr, &sin_size)) >0)  
  443.     {  
  444.         if(strncmp(recvbuf, "over",4) == 0)  
  445.   
  446.         {  
  447.   
  448.             break;  
  449.   
  450.         }  
  451.         poutfile = fopen(outputfilename,"ab+");  
  452.         rtp_unpackage(recvbuf,receive_bytes);  
  453.         fclose(poutfile);  
  454.     }  
  455.     strcpy(sendbuf, "success");  
  456.     sendto( sockfd, sendbuf, BUFFER_SIZE, 0 ,(struct sockaddr *)&client_sockaddr, sin_size);  
  457.     close(client_fd);  
  458.     close(sockfd);  
  459.     return 0;  
  460. }  
  1. #include <stdio.h>  
  2.   
  3. #include <stdlib.h>  
  4.   
  5. #include <string.h>  
  6.   
  7. #include <sys/socket.h>  
  8.   
  9. #include <netinet/in.h>  
  10. #include <arpa/inet.h>  
  11.   
  12. #include <unistd.h>  
  13.   
  14. #include <errno.h>  
  15.   
  16. #include <sys/types.h>  
  17.   
  18. #include <fcntl.h>  
  19.   
  20. typedef struct  
  21. {  
  22.     unsigned char version;              //!< Version, 2 bits, MUST be 0x2  
  23.     unsigned char padding;              //!< Padding bit, Padding MUST NOT be used  
  24.     unsigned char extension;            //!< Extension, MUST be zero  
  25.     unsigned char cc;                   //!< CSRC count, normally 0 in the absence of RTP mixers           
  26.     unsigned char marker;               //!< Marker bit  
  27.     unsigned char pt;                   //!< 7 bits, Payload Type, dynamically established  
  28.     unsigned int seq_no;                //!< RTP sequence number, incremented by one for each sent packet   
  29.     unsigned int timestamp;        //!< timestamp, 27 MHz for H.264  
  30.     unsigned int ssrc;             //!< Synchronization Source, chosen randomly  
  31.     unsigned char * payload;      //!< the payload including payload headers  
  32.     unsigned int paylen;           //!< length of payload in bytes  
  33. } RTPpacket_t;  
  34.   
  35. typedef struct   
  36. {  
  37.     /*  0                   1                   2                   3 
  38.     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 
  39.     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
  40.     |V=2|P|X|  CC   |M|     PT      |       sequence number         | 
  41.     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
  42.     |                           timestamp                           | 
  43.     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
  44.     |           synchronization source (SSRC) identifier            | 
  45.     +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 
  46.     |            contributing source (CSRC) identifiers             | 
  47.     |                             ....                              | 
  48.     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
  49.     */  
  50.     //intel 的cpu 是intel为小端字节序(低端存到底地址) 而网络流为大端字节序(高端存到低地址)  
  51.     /*intel 的cpu : 高端->csrc_len:4 -> extension:1-> padding:1 -> version:2 ->低端 
  52.      在内存中存储 : 
  53.      低->4001(内存地址)version:2 
  54.          4002(内存地址)padding:1 
  55.          4003(内存地址)extension:1 
  56.      高->4004(内存地址)csrc_len:4 
  57.  
  58.      网络传输解析 : 高端->version:2->padding:1->extension:1->csrc_len:4->低端  (为正确的文档描述格式) 
  59.  
  60.      存入接收内存 : 
  61.      低->4001(内存地址)version:2 
  62.          4002(内存地址)padding:1 
  63.          4003(内存地址)extension:1 
  64.      高->4004(内存地址)csrc_len:4 
  65.      本地内存解析 :高端->csrc_len:4 -> extension:1-> padding:1 -> version:2 ->低端 , 
  66.      即: 
  67.      unsigned char csrc_len:4;        // expect 0  
  68.      unsigned char extension:1;       // expect 1 
  69.      unsigned char padding:1;         // expect 0  
  70.      unsigned char version:2;         // expect 2  
  71.     */  
  72.     /* byte 0 */  
  73.      unsigned char csrc_len:4;        /* expect 0 */  
  74.      unsigned char extension:1;       /* expect 1, see RTP_OP below */  
  75.      unsigned char padding:1;         /* expect 0 */  
  76.      unsigned char version:2;         /* expect 2 */  
  77.     /* byte 1 */  
  78.      unsigned char payloadtype:7;     /* RTP_PAYLOAD_RTSP */  
  79.      unsigned char marker:1;          /* expect 1 */  
  80.     /* bytes 2,3 */  
  81.      unsigned int seq_no;              
  82.     /* bytes 4-7 */  
  83.      unsigned int timestamp;          
  84.     /* bytes 8-11 */  
  85.      unsigned int ssrc;              /* stream number is used here. */  
  86. } RTP_FIXED_HEADER;  
  87.   
  88.   
  89. typedef struct  
  90. {  
  91.     unsigned char forbidden_bit;           //! Should always be FALSE  
  92.     unsigned char nal_reference_idc;       //! NALU_PRIORITY_xxxx  
  93.     unsigned char nal_unit_type;           //! NALU_TYPE_xxxx    
  94.     unsigned int startcodeprefix_len;      //! 前缀字节数  
  95.     unsigned int len;                      //! 包含nal 头的nal 长度,从第一个00000001到下一个000000001的长度  
  96.     unsigned int max_size;                 //! 做多一个nal 的长度  
  97.     unsigned char * buf;                   //! 包含nal 头的nal 数据  
  98.     unsigned int lost_packets;             //! 预留  
  99. } NALU_t;  
  100.   
  101. /* 
  102. +---------------+ 
  103. |0|1|2|3|4|5|6|7| 
  104. +-+-+-+-+-+-+-+-+ 
  105. |F|NRI|  Type   | 
  106. +---------------+ 
  107. */  
  108. typedef struct   
  109. {  
  110.     //byte 0  
  111.     unsigned char TYPE:5;  
  112.     unsigned char NRI:2;  
  113.     unsigned char F:1;          
  114. } NALU_HEADER; // 1 BYTE   
  115.   
  116. /* 
  117. +---------------+ 
  118. |0|1|2|3|4|5|6|7| 
  119. +-+-+-+-+-+-+-+-+ 
  120. |F|NRI|  Type   | 
  121. +---------------+ 
  122. */  
  123. typedef struct   
  124. {  
  125.     //byte 0  
  126.     unsigned char TYPE:5;  
  127.     unsigned char NRI:2;   
  128.     unsigned char F:1;                
  129. } FU_INDICATOR; // 1 BYTE   
  130.   
  131. /* 
  132. +---------------+ 
  133. |0|1|2|3|4|5|6|7| 
  134. +-+-+-+-+-+-+-+-+ 
  135. |S|E|R|  Type   | 
  136. +---------------+ 
  137. */  
  138. typedef struct   
  139. {  
  140.     //byte 0  
  141.     unsigned char TYPE:5;  
  142.     unsigned char R:1;  
  143.     unsigned char E:1;  
  144.     unsigned char S:1;      
  145. } FU_HEADER;   // 1 BYTES   
  146.   
  147. #define  MAXDATASIZE 1500  
  148. #define PORT    1234  
  149. #define BUFFER_SIZE 10  
  150.   
  151. FILE * poutfile =  NULL;      
  152.   
  153. char * outputfilename = "./receive.264";  
  154.   
  155. int  OpenBitstreamFile (char *fn)  
  156. {  
  157.     if (NULL == (poutfile = fopen(fn, "wb")))  
  158.     {  
  159.         printf("Error: Open input file error\n");  
  160.         getchar();  
  161.     }  
  162.     return 1;  
  163. }  
  164.   
  165. NALU_t *AllocNALU(int buffersize)  
  166. {  
  167.     NALU_t *n;  
  168.   
  169.     if ((n = (NALU_t*)calloc (1, sizeof(NALU_t))) == NULL)  
  170.     {  
  171.         printf("AllocNALU Error: Allocate Meory To NALU_t Failed ");  
  172.         exit(0);  
  173.     }  
  174.     return n;  
  175. }  
  176.   
  177. void FreeNALU(NALU_t *n)  
  178. {  
  179.     if (n)  
  180.     {  
  181.         free (n);  
  182.     }  
  183. }  
  184.   
  185. /* 
  186. *bufIn:rtppackage 
  187. *len: the lengthe of rtppackage 
  188. */  
  189. void rtp_unpackage(char *bufIn,int len)  
  190. {  
  191.     unsigned char recvbuf[1500];  
  192.     RTPpacket_t *p = NULL;   
  193.     RTP_FIXED_HEADER * rtp_hdr = NULL;  
  194.     NALU_HEADER * nalu_hdr = NULL;  
  195.     NALU_t * n  = NULL;  
  196.     FU_INDICATOR    *fu_ind = NULL;  
  197.     FU_HEADER       *fu_hdr= NULL;  
  198.     int total_bytes = 0;                 //当前包传出的数据  
  199.     static int total_recved = 0;         //一共传输的数据  
  200.     int fwrite_number = 0;               //存入文件的数据长度  
  201.   
  202.     memcpy(recvbuf,bufIn, len);          //复制rtp包   
  203.     printf("包长度+ rtp头:   = %d\n",len);  
  204.   
  205.     //  
  206.     //begin rtp_payload and rtp_header  
  207.   
  208.     p = (RTPpacket_t*)&recvbuf[0];  
  209.     if ((p = malloc (sizeof (RTPpacket_t)))== NULL)  
  210.     {  
  211.         printf ("RTPpacket_t MMEMORY ERROR\n");  
  212.     }  
  213.     if ((p->payload = malloc (MAXDATASIZE))== NULL)  
  214.     {  
  215.         printf ("RTPpacket_t payload MMEMORY ERROR\n");  
  216.     }  
  217.   
  218.     if ((rtp_hdr = malloc(sizeof(RTP_FIXED_HEADER))) == NULL)  
  219.     {  
  220.         printf("RTP_FIXED_HEADER MEMORY ERROR\n");  
  221.     }  
  222.       
  223.     rtp_hdr =(RTP_FIXED_HEADER*)&recvbuf[0];   
  224.     printf("版本号     : %d\n",rtp_hdr->version);  
  225.     p->version  = rtp_hdr->version;  
  226.     p->padding  = rtp_hdr->padding;  
  227.     p->extension  = rtp_hdr->extension;  
  228.     p->cc = rtp_hdr->csrc_len;  
  229.     printf("标志位     : %d\n",rtp_hdr->marker);  
  230.     p->marker = rtp_hdr->marker;  
  231.     printf("负载类型    :%d\n",rtp_hdr->payloadtype);  
  232.     p->pt = rtp_hdr->payloadtype;  
  233.     printf("包号      : %d \n",rtp_hdr->seq_no);  
  234.     p->seq_no = rtp_hdr->seq_no;  
  235.     printf("时间戳     : %d\n",rtp_hdr->timestamp);  
  236.     p->timestamp = rtp_hdr->timestamp;  
  237.     printf("帧号      : %d\n",rtp_hdr->ssrc);  
  238.     p->ssrc = rtp_hdr->ssrc;  
  239.       
  240.     //end rtp_payload and rtp_header  
  241.     //  
  242.     //begin nal_hdr  
  243.     if (!(n = AllocNALU(800000)))          //为结构体nalu_t及其成员buf分配空间。返回值为指向nalu_t存储空间的指针  
  244.     {  
  245.         printf("NALU_t MMEMORY ERROR\n");  
  246.     }  
  247.     if ((nalu_hdr = malloc(sizeof(NALU_HEADER))) == NULL)  
  248.     {  
  249.         printf("NALU_HEADER MEMORY ERROR\n");  
  250.     }  
  251.   
  252.     nalu_hdr =(NALU_HEADER*)&recvbuf[12];                        //网络传输过来的字节序 ,当存入内存还是和文档描述的相反,只要匹配网络字节序和文档描述即可传输正确。  
  253.     printf("forbidden_zero_bit: %d\n",nalu_hdr->F);              //网络传输中的方式为:F->NRI->TYPE.. 内存中存储方式为 TYPE->NRI->F (和nal头匹配)。  
  254.     n->forbidden_bit= nalu_hdr->F << 7;                          //内存中的字节序。  
  255.     printf("nal_reference_idc:  %d\n",nalu_hdr->NRI);  
  256.     n->nal_reference_idc = nalu_hdr->NRI << 5;                        
  257.     printf("nal 负载类型:       %d\n",nalu_hdr->TYPE);  
  258.     n->nal_unit_type = nalu_hdr->TYPE;  
  259.   
  260.     //end nal_hdr  
  261.     //  
  262.     //开始解包  
  263.     if ( nalu_hdr->TYPE  == 0)  
  264.     {  
  265.         printf("这个包有错误,0无定义\n");  
  266.     }  
  267.     else if ( nalu_hdr->TYPE >0 &&  nalu_hdr->TYPE < 24)  //单包  
  268.     {  
  269.         printf("当前包为单包\n");  
  270.         putc(0x00, poutfile);  
  271.         putc(0x00, poutfile);  
  272.         putc(0x00, poutfile);  
  273.         putc(0x01, poutfile);   //写进起始字节0x00000001  
  274.         total_bytes +=4;  
  275.         memcpy(p->payload,&recvbuf[13],len-13);    
  276.         p->paylen = len-13;  
  277.         fwrite(nalu_hdr,1,1,poutfile);  //写NAL_HEADER  
  278.         total_bytes += 1;  
  279.         fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);  //写NAL数据  
  280.         total_bytes = p->paylen;  
  281.         printf("包长度 + nal= %d\n",total_bytes);  
  282.     }  
  283.     else if ( nalu_hdr->TYPE == 24)                    //STAP-A   单一时间的组合包  
  284.     {  
  285.         printf("当前包为STAP-A\n");  
  286.     }  
  287.     else if ( nalu_hdr->TYPE == 25)                    //STAP-B   单一时间的组合包  
  288.     {  
  289.         printf("当前包为STAP-B\n");  
  290.     }  
  291.     else if (nalu_hdr->TYPE == 26)                     //MTAP16   多个时间的组合包  
  292.     {  
  293.         printf("当前包为MTAP16\n");  
  294.     }  
  295.     else if ( nalu_hdr->TYPE == 27)                    //MTAP24   多个时间的组合包  
  296.     {  
  297.         printf("当前包为MTAP24\n");  
  298.     }  
  299.      else if ( nalu_hdr->TYPE == 28)                    //FU-A分片包,解码顺序和传输顺序相同  
  300.     {  
  301.         if ((fu_ind = malloc(sizeof(FU_INDICATOR))) == NULL)  
  302.         {  
  303.             printf("FU_INDICATOR MEMORY ERROR\n");  
  304.         }  
  305.         if ((fu_hdr = malloc(sizeof(FU_HEADER))) == NULL)  
  306.         {  
  307.             printf("FU_HEADER MEMORY ERROR\n");  
  308.         }  
  309.   
  310.         fu_ind=(FU_INDICATOR*)&recvbuf[12];     //分片包用的是FU_INDICATOR而不是NALU_HEADER  
  311.         printf("FU_INDICATOR->F     :%d\n",fu_ind->F);  
  312.         n->forbidden_bit = fu_ind->F << 7;  
  313.         printf("FU_INDICATOR->NRI   :%d\n",fu_ind->NRI);  
  314.         n->nal_reference_idc = fu_ind->NRI << 5;                        
  315.         printf("FU_INDICATOR->TYPE  :%d\n",fu_ind->TYPE);  
  316.         n->nal_unit_type = fu_ind->TYPE;  
  317.   
  318.         fu_hdr=(FU_HEADER*)&recvbuf[13];        //FU_HEADER赋值  
  319.         printf("FU_HEADER->S        :%d\n",fu_hdr->S);  
  320.         printf("FU_HEADER->E        :%d\n",fu_hdr->E);  
  321.         printf("FU_HEADER->R        :%d\n",fu_hdr->R);  
  322.         printf("FU_HEADER->TYPE     :%d\n",fu_hdr->TYPE);  
  323.         n->nal_unit_type = fu_hdr->TYPE;               //应用的是FU_HEADER的TYPE  
  324.   
  325.         if (rtp_hdr->marker == 1)                      //分片包最后一个包  
  326.         {  
  327.             printf("当前包为FU-A分片包最后一个包\n");  
  328.             memcpy(p->payload,&recvbuf[14],len - 14);  
  329.             p->paylen = len - 14;  
  330.             fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);  //写NAL数据  
  331.             total_bytes = p->paylen;  
  332.             printf("包长度 + FU = %d\n",total_bytes);    
  333.         }  
  334.         else if (rtp_hdr->marker == 0)                 //分片包 但不是最后一个包  
  335.         {  
  336.             if (fu_hdr->S == 1)                        //分片的第一个包  
  337.             {  
  338.                 unsigned char F;  
  339.                 unsigned char NRI;  
  340.                 unsigned char TYPE;  
  341.                 unsigned char nh;  
  342.                 printf("当前包为FU-A分片包第一个包\n");  
  343.                 putc(0x00, poutfile);  
  344.                 putc(0x00, poutfile);  
  345.                 putc(0x00, poutfile);  
  346.                 putc(0x01, poutfile);               //写起始字节码0x00000001  
  347.                 total_bytes += 4;  
  348.                   
  349.                 F = fu_ind->F << 7;  
  350.                 NRI = fu_ind->NRI << 5;  
  351.                 TYPE = fu_hdr->TYPE;                                            //应用的是FU_HEADER的TYPE  
  352.                 //nh = n->forbidden_bit|n->nal_reference_idc|n->nal_unit_type;  //二进制文件也是按 大字节序存储  
  353.                 nh = F | NRI | TYPE;  
  354.   
  355.                 putc(nh,poutfile);              //写NAL HEADER  
  356.   
  357.                 total_bytes +=1;  
  358.                 memcpy(p->payload,&recvbuf[14],len - 14);  
  359.                 p->paylen = len - 14;  
  360.                 fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);  //写NAL数据  
  361.                 total_bytes = p->paylen;  
  362.                 printf("包长度 + FU_First = %d\n",total_bytes);      
  363.             }  
  364.             else                                      //如果不是第一个包  
  365.             {  
  366.                 printf("当前包为FU-A分片包\n");  
  367.                 memcpy(p->payload,&recvbuf[14],len - 14);  
  368.                 p->paylen= len - 14;  
  369.                 fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);  //写NAL数据  
  370.                 total_bytes = p->paylen;  
  371.                 printf("包长度 + FU = %d\n",total_bytes);    
  372.             }     
  373.         }  
  374.     }  
  375.     else if ( nalu_hdr->TYPE == 29)                //FU-B分片包,解码顺序和传输顺序相同  
  376.     {  
  377.         if (rtp_hdr->marker == 1)                  //分片包最后一个包  
  378.         {  
  379.             printf("当前包为FU-B分片包最后一个包\n");  
  380.   
  381.         }  
  382.         else if (rtp_hdr->marker == 0)             //分片包 但不是最后一个包  
  383.         {  
  384.             printf("当前包为FU-B分片包\n");  
  385.         }  
  386.     }  
  387.     else  
  388.     {  
  389.         printf("这个包有错误,30-31 没有定义\n");  
  390.     }  
  391.     total_recved += total_bytes;  
  392.     printf("total_recved = %d\n",total_recved);  
  393.     memset(recvbuf,0,1500);  
  394.     free (p->payload);  
  395.     free (p);  
  396.     FreeNALU(n);  
  397.     //结束解包  
  398.     //  
  399.     return ;  
  400. }  
  401.   
  402.   
  403. int main()  
  404. {  
  405.     char recvbuf[MAXDATASIZE];  //加上头最大传输数据 1500  
  406.     int sockfd;    
  407.     int client_fd;    
  408.     int sin_size;    
  409.     char sendbuf[BUFFER_SIZE];  
  410.     struct sockaddr_in server_sockaddr, client_sockaddr;    
  411.   
  412.     int receive_bytes = 0;  
  413.   
  414.     OpenBitstreamFile(outputfilename);   
  415.       
  416.     //  
  417.     //socket 操作  
  418.       
  419.     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)  
  420.     {  
  421.         perror("socket");  
  422.         exit(1);  
  423.     }//建立socket链接,数据报socket,IPv4协议  
  424.     printf("create socket success!\n");  
  425.   
  426.     server_sockaddr.sin_family = AF_INET;    
  427.     server_sockaddr.sin_addr.s_addr = INADDR_ANY;//0.0.0.0不确定地址    
  428.     server_sockaddr.sin_port = htons(PORT);    
  429.     bzero(&(server_sockaddr.sin_zero), 8);  //填充0以保持与struct sockaddr同样大小  
  430.   
  431.     if (bind(sockfd, (struct sockaddr *) &server_sockaddr,    
  432.           sizeof(struct sockaddr)) < 0)     
  433.     {  
  434.         perror("ERROR on binding");  
  435.         exit(1);   
  436.     }   
  437.     printf("bind success!\n");  
  438.   
  439.     sin_size = sizeof(struct sockaddr_in);  
  440.     printf("waiting for client connection...\n");  
  441.     //接收从客户端发来的数据  
  442.     while((receive_bytes = recvfrom(sockfd, recvbuf, MAXDATASIZE, 0, (struct sockaddr *)&client_sockaddr, &sin_size)) >0)  
  443.     {  
  444.         if(strncmp(recvbuf, "over",4) == 0)  
  445.   
  446.         {  
  447.   
  448.             break;  
  449.   
  450.         }  
  451.         poutfile = fopen(outputfilename,"ab+");  
  452.         rtp_unpackage(recvbuf,receive_bytes);  
  453.         fclose(poutfile);  
  454.     }  
  455.     strcpy(sendbuf, "success");  
  456.     sendto( sockfd, sendbuf, BUFFER_SIZE, 0 ,(struct sockaddr *)&client_sockaddr, sin_size);  
  457.     close(client_fd);  
  458.     close(sockfd);  
  459.     return 0;  
  460. }  
  1. #include <stdio.h>   
  2.   
  3. #include <stdlib.h>   
  4.   
  5. #include <string.h>   
  6.   
  7. #include <sys/socket.h>   
  8.   
  9. #include <netinet/in.h>   
  10. #include <arpa/inet.h>   
  11.   
  12. #include <unistd.h>   
  13.   
  14. #include <errno.h>   
  15.   
  16. #include <sys/types.h>   
  17.   
  18. #include <fcntl.h>   
  19.   
  20. typedef struct  
  21. {  
  22.     unsigned char version;              //!< Version, 2 bits, MUST be 0x2   
  23.     unsigned char padding;              //!< Padding bit, Padding MUST NOT be used   
  24.     unsigned char extension;            //!< Extension, MUST be zero   
  25.     unsigned char cc;                   //!< CSRC count, normally 0 in the absence of RTP mixers            
  26.     unsigned char marker;               //!< Marker bit   
  27.     unsigned char pt;                   //!< 7 bits, Payload Type, dynamically established   
  28.     unsigned int seq_no;                //!< RTP sequence number, incremented by one for each sent packet    
  29.     unsigned int timestamp;        //!< timestamp, 27 MHz for H.264   
  30.     unsigned int ssrc;             //!< Synchronization Source, chosen randomly   
  31.     unsigned char * payload;      //!< the payload including payload headers   
  32.     unsigned int paylen;           //!< length of payload in bytes   
  33. } RTPpacket_t;  
  34.   
  35. typedef struct   
  36. {  
  37.     /*  0                   1                   2                   3 
  38.     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 
  39.     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
  40.     |V=2|P|X|  CC   |M|     PT      |       sequence number         | 
  41.     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
  42.     |                           timestamp                           | 
  43.     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
  44.     |           synchronization source (SSRC) identifier            | 
  45.     +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 
  46.     |            contributing source (CSRC) identifiers             | 
  47.     |                             ....                              | 
  48.     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
  49.     */  
  50.     //intel 的cpu 是intel为小端字节序(低端存到底地址) 而网络流为大端字节序(高端存到低地址)   
  51.     /*intel 的cpu : 高端->csrc_len:4 -> extension:1-> padding:1 -> version:2 ->低端 
  52.      在内存中存储 : 
  53.      低->4001(内存地址)version:2 
  54.          4002(内存地址)padding:1 
  55.          4003(内存地址)extension:1 
  56.      高->4004(内存地址)csrc_len:4 
  57.  
  58.      网络传输解析 : 高端->version:2->padding:1->extension:1->csrc_len:4->低端  (为正确的文档描述格式) 
  59.  
  60.      存入接收内存 : 
  61.      低->4001(内存地址)version:2 
  62.          4002(内存地址)padding:1 
  63.          4003(内存地址)extension:1 
  64.      高->4004(内存地址)csrc_len:4 
  65.      本地内存解析 :高端->csrc_len:4 -> extension:1-> padding:1 -> version:2 ->低端 , 
  66.      即: 
  67.      unsigned char csrc_len:4;        // expect 0  
  68.      unsigned char extension:1;       // expect 1 
  69.      unsigned char padding:1;         // expect 0  
  70.      unsigned char version:2;         // expect 2  
  71.     */  
  72.     /* byte 0 */  
  73.      unsigned char csrc_len:4;        /* expect 0 */  
  74.      unsigned char extension:1;       /* expect 1, see RTP_OP below */  
  75.      unsigned char padding:1;         /* expect 0 */  
  76.      unsigned char version:2;         /* expect 2 */  
  77.     /* byte 1 */  
  78.      unsigned char payloadtype:7;     /* RTP_PAYLOAD_RTSP */  
  79.      unsigned char marker:1;          /* expect 1 */  
  80.     /* bytes 2,3 */  
  81.      unsigned int seq_no;              
  82.     /* bytes 4-7 */  
  83.      unsigned int timestamp;          
  84.     /* bytes 8-11 */  
  85.      unsigned int ssrc;              /* stream number is used here. */  
  86. } RTP_FIXED_HEADER;  
  87.   
  88.   
  89. typedef struct  
  90. {  
  91.     unsigned char forbidden_bit;           //! Should always be FALSE   
  92.     unsigned char nal_reference_idc;       //! NALU_PRIORITY_xxxx   
  93.     unsigned char nal_unit_type;           //! NALU_TYPE_xxxx     
  94.     unsigned int startcodeprefix_len;      //! 前缀字节数   
  95.     unsigned int len;                      //! 包含nal 头的nal 长度,从第一个00000001到下一个000000001的长度   
  96.     unsigned int max_size;                 //! 做多一个nal 的长度   
  97.     unsigned char * buf;                   //! 包含nal 头的nal 数据   
  98.     unsigned int lost_packets;             //! 预留   
  99. } NALU_t;  
  100.   
  101. /* 
  102. +---------------+ 
  103. |0|1|2|3|4|5|6|7| 
  104. +-+-+-+-+-+-+-+-+ 
  105. |F|NRI|  Type   | 
  106. +---------------+ 
  107. */  
  108. typedef struct   
  109. {  
  110.     //byte 0   
  111.     unsigned char TYPE:5;  
  112.     unsigned char NRI:2;  
  113.     unsigned char F:1;          
  114. } NALU_HEADER; // 1 BYTE    
  115.   
  116. /* 
  117. +---------------+ 
  118. |0|1|2|3|4|5|6|7| 
  119. +-+-+-+-+-+-+-+-+ 
  120. |F|NRI|  Type   | 
  121. +---------------+ 
  122. */  
  123. typedef struct   
  124. {  
  125.     //byte 0   
  126.     unsigned char TYPE:5;  
  127.     unsigned char NRI:2;   
  128.     unsigned char F:1;                
  129. } FU_INDICATOR; // 1 BYTE    
  130.   
  131. /* 
  132. +---------------+ 
  133. |0|1|2|3|4|5|6|7| 
  134. +-+-+-+-+-+-+-+-+ 
  135. |S|E|R|  Type   | 
  136. +---------------+ 
  137. */  
  138. typedef struct   
  139. {  
  140.     //byte 0   
  141.     unsigned char TYPE:5;  
  142.     unsigned char R:1;  
  143.     unsigned char E:1;  
  144.     unsigned char S:1;      
  145. } FU_HEADER;   // 1 BYTES    
  146.   
  147. #define  MAXDATASIZE 1500   
  148. #define PORT    1234   
  149. #define BUFFER_SIZE 10   
  150.   
  151. FILE * poutfile =  NULL;      
  152.   
  153. char * outputfilename = "./receive.264";  
  154.   
  155. int  OpenBitstreamFile (char *fn)  
  156. {  
  157.     if (NULL == (poutfile = fopen(fn, "wb")))  
  158.     {  
  159.         printf("Error: Open input file error\n");  
  160.         getchar();  
  161.     }  
  162.     return 1;  
  163. }  
  164.   
  165. NALU_t *AllocNALU(int buffersize)  
  166. {  
  167.     NALU_t *n;  
  168.   
  169.     if ((n = (NALU_t*)calloc (1, sizeof(NALU_t))) == NULL)  
  170.     {  
  171.         printf("AllocNALU Error: Allocate Meory To NALU_t Failed ");  
  172.         exit(0);  
  173.     }  
  174.     return n;  
  175. }  
  176.   
  177. void FreeNALU(NALU_t *n)  
  178. {  
  179.     if (n)  
  180.     {  
  181.         free (n);  
  182.     }  
  183. }  
  184.   
  185. /* 
  186. *bufIn:rtppackage 
  187. *len: the lengthe of rtppackage 
  188. */  
  189. void rtp_unpackage(char *bufIn,int len)  
  190. {  
  191.     unsigned char recvbuf[1500];  
  192.     RTPpacket_t *p = NULL;   
  193.     RTP_FIXED_HEADER * rtp_hdr = NULL;  
  194.     NALU_HEADER * nalu_hdr = NULL;  
  195.     NALU_t * n  = NULL;  
  196.     FU_INDICATOR    *fu_ind = NULL;  
  197.     FU_HEADER       *fu_hdr= NULL;  
  198.     int total_bytes = 0;                 //当前包传出的数据   
  199.     static int total_recved = 0;         //一共传输的数据   
  200.     int fwrite_number = 0;               //存入文件的数据长度   
  201.   
  202.     memcpy(recvbuf,bufIn, len);          //复制rtp包    
  203.     printf("包长度+ rtp头:   = %d\n",len);  
  204.   
  205.     //   
  206.     //begin rtp_payload and rtp_header   
  207.   
  208.     p = (RTPpacket_t*)&recvbuf[0];  
  209.     if ((p = malloc (sizeof (RTPpacket_t)))== NULL)  
  210.     {  
  211.         printf ("RTPpacket_t MMEMORY ERROR\n");  
  212.     }  
  213.     if ((p->payload = malloc (MAXDATASIZE))== NULL)  
  214.     {  
  215.         printf ("RTPpacket_t payload MMEMORY ERROR\n");  
  216.     }  
  217.   
  218.     if ((rtp_hdr = malloc(sizeof(RTP_FIXED_HEADER))) == NULL)  
  219.     {  
  220.         printf("RTP_FIXED_HEADER MEMORY ERROR\n");  
  221.     }  
  222.       
  223.     rtp_hdr =(RTP_FIXED_HEADER*)&recvbuf[0];   
  224.     printf("版本号     : %d\n",rtp_hdr->version);  
  225.     p->version  = rtp_hdr->version;  
  226.     p->padding  = rtp_hdr->padding;  
  227.     p->extension  = rtp_hdr->extension;  
  228.     p->cc = rtp_hdr->csrc_len;  
  229.     printf("标志位     : %d\n",rtp_hdr->marker);  
  230.     p->marker = rtp_hdr->marker;  
  231.     printf("负载类型    :%d\n",rtp_hdr->payloadtype);  
  232.     p->pt = rtp_hdr->payloadtype;  
  233.     printf("包号      : %d \n",rtp_hdr->seq_no);  
  234.     p->seq_no = rtp_hdr->seq_no;  
  235.     printf("时间戳     : %d\n",rtp_hdr->timestamp);  
  236.     p->timestamp = rtp_hdr->timestamp;  
  237.     printf("帧号      : %d\n",rtp_hdr->ssrc);  
  238.     p->ssrc = rtp_hdr->ssrc;  
  239.       
  240.     //end rtp_payload and rtp_header   
  241.     //   
  242.     //begin nal_hdr   
  243.     if (!(n = AllocNALU(800000)))          //为结构体nalu_t及其成员buf分配空间。返回值为指向nalu_t存储空间的指针   
  244.     {  
  245.         printf("NALU_t MMEMORY ERROR\n");  
  246.     }  
  247.     if ((nalu_hdr = malloc(sizeof(NALU_HEADER))) == NULL)  
  248.     {  
  249.         printf("NALU_HEADER MEMORY ERROR\n");  
  250.     }  
  251.   
  252.     nalu_hdr =(NALU_HEADER*)&recvbuf[12];                        //网络传输过来的字节序 ,当存入内存还是和文档描述的相反,只要匹配网络字节序和文档描述即可传输正确。   
  253.     printf("forbidden_zero_bit: %d\n",nalu_hdr->F);              //网络传输中的方式为:F->NRI->TYPE.. 内存中存储方式为 TYPE->NRI->F (和nal头匹配)。   
  254.     n->forbidden_bit= nalu_hdr->F << 7;                          //内存中的字节序。   
  255.     printf("nal_reference_idc:  %d\n",nalu_hdr->NRI);  
  256.     n->nal_reference_idc = nalu_hdr->NRI << 5;                        
  257.     printf("nal 负载类型:       %d\n",nalu_hdr->TYPE);  
  258.     n->nal_unit_type = nalu_hdr->TYPE;  
  259.   
  260.     //end nal_hdr   
  261.     //   
  262.     //开始解包   
  263.     if ( nalu_hdr->TYPE  == 0)  
  264.     {  
  265.         printf("这个包有错误,0无定义\n");  
  266.     }  
  267.     else if ( nalu_hdr->TYPE >0 &&  nalu_hdr->TYPE < 24)  //单包   
  268.     {  
  269.         printf("当前包为单包\n");  
  270.         putc(0x00, poutfile);  
  271.         putc(0x00, poutfile);  
  272.         putc(0x00, poutfile);  
  273.         putc(0x01, poutfile);   //写进起始字节0x00000001   
  274.         total_bytes +=4;  
  275.         memcpy(p->payload,&recvbuf[13],len-13);    
  276.         p->paylen = len-13;  
  277.         fwrite(nalu_hdr,1,1,poutfile);  //写NAL_HEADER   
  278.         total_bytes += 1;  
  279.         fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);  //写NAL数据   
  280.         total_bytes = p->paylen;  
  281.         printf("包长度 + nal= %d\n",total_bytes);  
  282.     }  
  283.     else if ( nalu_hdr->TYPE == 24)                    //STAP-A   单一时间的组合包   
  284.     {  
  285.         printf("当前包为STAP-A\n");  
  286.     }  
  287.     else if ( nalu_hdr->TYPE == 25)                    //STAP-B   单一时间的组合包   
  288.     {  
  289.         printf("当前包为STAP-B\n");  
  290.     }  
  291.     else if (nalu_hdr->TYPE == 26)                     //MTAP16   多个时间的组合包   
  292.     {  
  293.         printf("当前包为MTAP16\n");  
  294.     }  
  295.     else if ( nalu_hdr->TYPE == 27)                    //MTAP24   多个时间的组合包   
  296.     {  
  297.         printf("当前包为MTAP24\n");  
  298.     }  
  299.      else if ( nalu_hdr->TYPE == 28)                    //FU-A分片包,解码顺序和传输顺序相同   
  300.     {  
  301.         if ((fu_ind = malloc(sizeof(FU_INDICATOR))) == NULL)  
  302.         {  
  303.             printf("FU_INDICATOR MEMORY ERROR\n");  
  304.         }  
  305.         if ((fu_hdr = malloc(sizeof(FU_HEADER))) == NULL)  
  306.         {  
  307.             printf("FU_HEADER MEMORY ERROR\n");  
  308.         }  
  309.   
  310.         fu_ind=(FU_INDICATOR*)&recvbuf[12];     //分片包用的是FU_INDICATOR而不是NALU_HEADER   
  311.         printf("FU_INDICATOR->F     :%d\n",fu_ind->F);  
  312.         n->forbidden_bit = fu_ind->F << 7;  
  313.         printf("FU_INDICATOR->NRI   :%d\n",fu_ind->NRI);  
  314.         n->nal_reference_idc = fu_ind->NRI << 5;                        
  315.         printf("FU_INDICATOR->TYPE  :%d\n",fu_ind->TYPE);  
  316.         n->nal_unit_type = fu_ind->TYPE;  
  317.   
  318.         fu_hdr=(FU_HEADER*)&recvbuf[13];        //FU_HEADER赋值   
  319.         printf("FU_HEADER->S        :%d\n",fu_hdr->S);  
  320.         printf("FU_HEADER->E        :%d\n",fu_hdr->E);  
  321.         printf("FU_HEADER->R        :%d\n",fu_hdr->R);  
  322.         printf("FU_HEADER->TYPE     :%d\n",fu_hdr->TYPE);  
  323.         n->nal_unit_type = fu_hdr->TYPE;               //应用的是FU_HEADER的TYPE   
  324.   
  325.         if (rtp_hdr->marker == 1)                      //分片包最后一个包   
  326.         {  
  327.             printf("当前包为FU-A分片包最后一个包\n");  
  328.             memcpy(p->payload,&recvbuf[14],len - 14);  
  329.             p->paylen = len - 14;  
  330.             fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);  //写NAL数据   
  331.             total_bytes = p->paylen;  
  332.             printf("包长度 + FU = %d\n",total_bytes);    
  333.         }  
  334.         else if (rtp_hdr->marker == 0)                 //分片包 但不是最后一个包   
  335.         {  
  336.             if (fu_hdr->S == 1)                        //分片的第一个包   
  337.             {  
  338.                 unsigned char F;  
  339.                 unsigned char NRI;  
  340.                 unsigned char TYPE;  
  341.                 unsigned char nh;  
  342.                 printf("当前包为FU-A分片包第一个包\n");  
  343.                 putc(0x00, poutfile);  
  344.                 putc(0x00, poutfile);  
  345.                 putc(0x00, poutfile);  
  346.                 putc(0x01, poutfile);               //写起始字节码0x00000001   
  347.                 total_bytes += 4;  
  348.                   
  349.                 F = fu_ind->F << 7;  
  350.                 NRI = fu_ind->NRI << 5;  
  351.                 TYPE = fu_hdr->TYPE;                                            //应用的是FU_HEADER的TYPE   
  352.                 //nh = n->forbidden_bit|n->nal_reference_idc|n->nal_unit_type;  //二进制文件也是按 大字节序存储   
  353.                 nh = F | NRI | TYPE;  
  354.   
  355.                 putc(nh,poutfile);              //写NAL HEADER   
  356.   
  357.                 total_bytes +=1;  
  358.                 memcpy(p->payload,&recvbuf[14],len - 14);  
  359.                 p->paylen = len - 14;  
  360.                 fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);  //写NAL数据   
  361.                 total_bytes = p->paylen;  
  362.                 printf("包长度 + FU_First = %d\n",total_bytes);      
  363.             }  
  364.             else                                      //如果不是第一个包   
  365.             {  
  366.                 printf("当前包为FU-A分片包\n");  
  367.                 memcpy(p->payload,&recvbuf[14],len - 14);  
  368.                 p->paylen= len - 14;  
  369.                 fwrite_number = fwrite(p->payload,1,p->paylen,poutfile);  //写NAL数据   
  370.                 total_bytes = p->paylen;  
  371.                 printf("包长度 + FU = %d\n",total_bytes);    
  372.             }     
  373.         }  
  374.     }  
  375.     else if ( nalu_hdr->TYPE == 29)                //FU-B分片包,解码顺序和传输顺序相同   
  376.     {  
  377.         if (rtp_hdr->marker == 1)                  //分片包最后一个包   
  378.         {  
  379.             printf("当前包为FU-B分片包最后一个包\n");  
  380.   
  381.         }  
  382.         else if (rtp_hdr->marker == 0)             //分片包 但不是最后一个包   
  383.         {  
  384.             printf("当前包为FU-B分片包\n");  
  385.         }  
  386.     }  
  387.     else  
  388.     {  
  389.         printf("这个包有错误,30-31 没有定义\n");  
  390.     }  
  391.     total_recved += total_bytes;  
  392.     printf("total_recved = %d\n",total_recved);  
  393.     memset(recvbuf,0,1500);  
  394.     free (p->payload);  
  395.     free (p);  
  396.     FreeNALU(n);  
  397.     //结束解包   
  398.     //   
  399.     return ;  
  400. }  
  401.   
  402.   
  403. int main()  
  404. {  
  405.     char recvbuf[MAXDATASIZE];  //加上头最大传输数据 1500   
  406.     int sockfd;    
  407.     int client_fd;    
  408.     int sin_size;    
  409.     char sendbuf[BUFFER_SIZE];  
  410.     struct sockaddr_in server_sockaddr, client_sockaddr;    
  411.   
  412.     int receive_bytes = 0;  
  413.   
  414.     OpenBitstreamFile(outputfilename);   
  415.       
  416.     //   
  417.     //socket 操作   
  418.       
  419.     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)  
  420.     {  
  421.         perror("socket");  
  422.         exit(1);  
  423.     }//建立socket链接,数据报socket,IPv4协议   
  424.     printf("create socket success!\n");  
  425.   
  426.     server_sockaddr.sin_family = AF_INET;    
  427.     server_sockaddr.sin_addr.s_addr = INADDR_ANY;//0.0.0.0不确定地址     
  428.     server_sockaddr.sin_port = htons(PORT);    
  429.     bzero(&(server_sockaddr.sin_zero), 8);  //填充0以保持与struct sockaddr同样大小   
  430.   
  431.     if (bind(sockfd, (struct sockaddr *) &server_sockaddr,    
  432.           sizeof(struct sockaddr)) < 0)     
  433.     {  
  434.         perror("ERROR on binding");  
  435.         exit(1);   
  436.     }   
  437.     printf("bind success!\n");  
  438.   
  439.     sin_size = sizeof(struct sockaddr_in);  
  440.     printf("waiting for client connection...\n");  
  441.     //接收从客户端发来的数据   
  442.     while((receive_bytes = recvfrom(sockfd, recvbuf, MAXDATASIZE, 0, (struct sockaddr *)&client_sockaddr, &sin_size)) >0)  
  443.     {  
  444.         if(strncmp(recvbuf, "over",4) == 0)  
  445.   
  446.         {  
  447.   
  448.             break;  
  449.   
  450.         }  
  451.         poutfile = fopen(outputfilename,"ab+");  
  452.         rtp_unpackage(recvbuf,receive_bytes);  
  453.         fclose(poutfile);  
  454.     }  
  455.     strcpy(sendbuf, "success");  
  456.     sendto( sockfd, sendbuf, BUFFER_SIZE, 0 ,(struct sockaddr *)&client_sockaddr, sin_size);  
  457.     close(client_fd);  
  458.     close(sockfd);  
  459.     return 0;  
  460. }  
#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。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值