全部博文(4)
分类: C/C++
2013-01-31 10:21:42
不完整,待编辑
h264toRTP.h
#ifndef _H264TORTP_H #define _H264TORTP_H #include/* Payload type */ #define H264 96 /* Timestamp */ #define CLKRATE 90000.0 #define SAMPLING CLKRATE /* * RTP HEADER : little-endian */ typedef struct RTP_HEADER{ /* byte 0 */ uint8_t csrc_len: 4; /* bit: 0~3 */ uint8_t extension: 1; /* bit: 4 */ uint8_t padding: 1; /* bit: 5 */ uint8_t version: 2; /* bit: 6~7 */ /* byte 1 */ uint8_t payload: 7; /* bit: 0~6 */ uint8_t marker: 1; /* bit: 7 */ /* byte 2 ~ 3 */ uint16_t seq_no; /* byte 4 ~ 7 */ uint32_t timestamp; /* byte 8 ~ 11 */ uint32_t ssrc; } __attribute__ ((packed)) RTP_HEADER_t; /* 12 bytes */ /* * All NAL units consist of a single NAL unit type octet, * which also co-serves as the payload header of this RTP payload format. * * +---------------+ * |0|1|2|3|4|5|6|7| * +-+-+-+-+-+-+-+-+ * |F|NRI| Type | * +---------------+ * * * TYPE:5 bits@nal_unit_type. * * * NRI:2 bits@nal_ref_idc. The semantics of value 00 and a non-zero value * remain unchanged from the H.264 specification. In other words, a value * of 00 indicates that the content of the NAL unit is not used to reconstruct * reference pictures for inter picture prediction. Such NAL units can be * discarded without risking the integrity of the reference pictures.Values * greater than 00 indicate that the decoding of the NAL unit is required * to maintain the integrity of the reference pictures.In addition to the * specification above, according to this RTP payload specification, values * of NRI greater than 00 indicate the relative transport priority,as determined * by the encoder. MANEs can use this information to protect more important * NAL units better than they do less important NAL units.The highest transport * priority is 11, followed by 10, and then by 01; finally,00 is the lowest. * * * F:1 bit@forbidden_zero_bit. A value of 0 indicates that the NAL unit type * octet and payload should not contain bit errors or other syntax violations. * A value of 1 indicates that the NAL unit type octet and payload may contain * bit errors or other syntax violations. */ typedef struct NALU_HEADER{ /* byte 0 */ uint8_t TYPE: 5; /* bit: 0~4 */ uint8_t NRI: 2; /* bit: 5~6 */ uint8_t F: 1; /* bit: 7 */ } __attribute__ ((packed)) NALU_HEADER_t; /* 1 bytes */ /* * */ typedef struct FU_INDICATOR { /* byte 0 */ uint8_t TYPE: 5; /* bit: 0~4 */ uint8_t NRI: 2; /* bit: 5~6 */ uint8_t F: 1; /* bit: 7 */ } __attribute__ ((packed)) FU_INDICATOR_t; /* 1 bytes */ /* * */ typedef struct FU_HEADER { /* byte 0 */ uint8_t TYPE: 5; /* bit: 0~4 */ uint8_t R: 1; /* bit: 5 */ uint8_t E: 1; /* bit: 6 */ uint8_t S: 1; /* bit: 7 */ } __attribute__ ((packed)) FU_HEADER_t; /* 1 bytes */ /* * */ typedef struct NALU { unsigned int nal_unit_type; unsigned int nal_ref_idc; unsigned int forbidden_zero_bit; unsigned int nalu_size; unsigned int nalu_offset; char *nalu_pbuf; } NALU_t; NALU_t *NALU_create(int size); void NALU_delete(NALU_t *nalu); int NALU_getPayload(NALU_t *nalu, char *pNalu); #endif
rtp_test.c
#include#include #include #include #include #include #include #include "h264toRTP.h" #include "rtcp.h" #define BUFFSIZE 1500 #define MTU_SIZE 1400 typedef struct sockaddr SA; /* Test file name */ char h264_file[] = "zhizuxia.264"; //char h264_file[] = "ti704_576.264"; //char h264_file[] = "idrnew2.264"; FILE *videoFile; static int locate_start_flags(char pbuf[]) { if(pbuf[0] != 0 || pbuf[1] != 0 || pbuf[2] != 0 || pbuf[3] != 1) return 0; else return 1; } NALU_t *NALU_create(int size) { NALU_t *nalu; nalu = (NALU_t *)calloc(1, sizeof(NALU_t)); if (NULL == nalu) { fprintf(stderr, "Failed to alloc space for NALU\n"); free(nalu); return NULL; } nalu->nalu_pbuf= (char *)calloc(1, size); if (NULL == nalu->nalu_pbuf) { fprintf(stderr, "Failed to alloc spaces for data.\n"); free(nalu); return NULL; } nalu->nalu_size = size; nalu->nalu_offset = 0; return nalu; } void NALU_delete(NALU_t *nalu) { if (nalu) { if (nalu->nalu_pbuf) { free(nalu->nalu_pbuf); nalu->nalu_pbuf = NULL; } free(nalu); nalu = NULL; } } int NALU_getPayload(NALU_t *nalu, char *pNalu) { int pos, flag = 0; memset(pNalu, 0, 2000000); if (4 != fread(pNalu, 1, 4, videoFile)) { fprintf(stderr, "Read start codes ERROR\n"); return -1; } else { pos = 4; } if (!locate_start_flags(&pNalu[0])) { fprintf(stderr, "start codes not found\n"); return -1; } while (!flag) { if(feof(videoFile)) { nalu->nalu_size = (pos - 1) - 4; memcpy (nalu->nalu_pbuf, &pNalu[4], nalu->nalu_size); nalu->forbidden_zero_bit = nalu->nalu_pbuf[0] & 0x80; nalu->nal_ref_idc = nalu->nalu_pbuf[0] & 0x60; nalu->nal_unit_type = nalu->nalu_pbuf[0] & 0x1f; return (pos - 1); } pNalu[pos++] = fgetc(videoFile); flag = locate_start_flags(&pNalu[pos - 4]); } if (0 != fseek(videoFile, -4, SEEK_CUR)) { fprintf(stderr, "Cannot fseek in the video stream file\n"); } nalu->nalu_size = (pos - 4) - 4; printf("data size : %d\n", nalu->nalu_size); memcpy(nalu->nalu_pbuf, &pNalu[4], nalu->nalu_size); nalu->forbidden_zero_bit = nalu->nalu_pbuf[0] & 0x80; nalu->nal_ref_idc = nalu->nalu_pbuf[0] & 0x60; nalu->nal_unit_type = nalu->nalu_pbuf[0] & 0x1f; return (pos - 4); } int main(int argc, char *argv[]) { unsigned short seq_num = 0; unsigned int ts_incremental = 0; unsigned int ts_current = 0; float framerate = 25; int bytes = 0; int connfd = -1; NALU_t *nalu = NULL; RTP_HEADER_t *rtp_hdr = NULL; NALU_HEADER_t *nalu_hdr = NULL; FU_INDICATOR_t *fu_indicator = NULL; FU_HEADER_t *fu_hdr = NULL; char *pNalu = NULL; char buf[BUFFSIZE] = {0,}; struct sockaddr_in peeraddr; int i, j, k; int count = 0, n = 0; printf("starting prog ...\n"); videoFile = fopen(h264_file, "rb"); if (NULL == videoFile) { fprintf(stderr, "cannot open h264 video file: %s\n", h264_file); goto cleanup; } nalu = NALU_create(4000000); if (NULL == nalu) { fprintf(stderr, "Failed to create NALU OBJECT\n"); goto cleanup; } pNalu = (char *)calloc(2000000, sizeof(char)); if (NULL == pNalu) { fprintf(stderr, "Failed to alloc tmpe space for nalu\n"); goto cleanup; } connfd = socket(AF_INET, SOCK_DGRAM, 0); if (-1 == connfd) { fprintf(stderr, "failed to create socket\n"); goto cleanup; } bzero(&peeraddr, sizeof(peeraddr)); peeraddr.sin_family = AF_INET; peeraddr.sin_port = htons(atoi("8888")); peeraddr.sin_addr.s_addr = inet_addr("192.168.0.78"); /* timesampe increasment */ ts_incremental = (unsigned int)(SAMPLING / framerate); while (!feof(videoFile)) { memset(buf, 0, BUFFSIZE); memset(nalu->nalu_pbuf, 0, nalu->nalu_size); rtp_hdr = (RTP_HEADER_t *)&buf[0]; rtp_hdr->payload = H264; rtp_hdr->version = 2; rtp_hdr->marker = 0; rtp_hdr->ssrc = htonl(10); n = NALU_getPayload(nalu, pNalu); printf("%d, %d\n", ++count, n); /* * Fragmentation unit: Used to fragment a single NAL unit over multiple RTP packets. * Exists with two versions, FU-A and FU-B, identified with the NAL unit type numbers 28 and 29, respectively. */ if (nalu->nalu_size > MTU_SIZE) { ts_current = ts_current + ts_incremental; rtp_hdr->timestamp = htonl(ts_current); /* */ j = nalu->nalu_size / MTU_SIZE; /* */ k = nalu->nalu_size % MTU_SIZE; printf("%d, %d\n", j, k); for (i = 0; i <= j; i++) { rtp_hdr->seq_no = htons(seq_num ++); if (0 == i) { printf("the 1st\n"); rtp_hdr->marker = 0; fu_indicator = (FU_INDICATOR_t *)&buf[12]; fu_indicator->F = nalu->forbidden_zero_bit; fu_indicator->NRI = nalu->nal_ref_idc >> 5; fu_indicator->TYPE = 28; fu_hdr = (FU_HEADER_t *)&buf[13]; fu_hdr->E = 0; fu_hdr->R = 0; fu_hdr->S = 1; fu_hdr->TYPE = nalu->nal_unit_type; memcpy(&buf[14], nalu->nalu_pbuf + 1, MTU_SIZE); bytes = MTU_SIZE + 14; sendto(connfd, buf, bytes, 0, (SA *)&peeraddr, sizeof(peeraddr)); } else if (j == i) { printf("the last\n"); rtp_hdr->marker = 1; fu_indicator = (FU_INDICATOR_t *)&buf[12]; fu_indicator->F = nalu->forbidden_zero_bit; fu_indicator->NRI = nalu->nal_ref_idc >> 5; fu_indicator->TYPE = 28; fu_hdr = (FU_HEADER_t *)&buf[13]; fu_hdr->E = 1; fu_hdr->R = 0; fu_hdr->S = 0; fu_hdr->TYPE = nalu->nal_unit_type; #if 0 if (k == 0) { bytes = MTU_SIZE + 14; memcpy(&buf[14], nalu->nalu_pbuf + i * MTU_SIZE + 1, MTU_SIZE); sendto(connfd, buf, bytes, 0, (SA *)&peeraddr, sizeof(peeraddr)); } else{ bytes = k- 1 + 14; memcpy(&buf[14], nalu->nalu_pbuf + i * MTU_SIZE + 1, k - 1); sendto(connfd, buf, bytes, 0, (SA *)&peeraddr, sizeof(peeraddr)); } #endif if (k == 0) break; bytes = k- 1 + 14; memcpy(&buf[14], nalu->nalu_pbuf + i * MTU_SIZE + 1, k - 1); sendto(connfd, buf, bytes, 0, (SA *)&peeraddr, sizeof(peeraddr)); /* control the rate of sending frame */ usleep(35000); } else { printf("############\n"); rtp_hdr->marker = 0; fu_indicator = (FU_INDICATOR_t *)&buf[12]; fu_indicator->F = nalu->forbidden_zero_bit; fu_indicator->NRI = nalu->nal_ref_idc >> 5; fu_indicator->TYPE = 28; fu_hdr = (FU_HEADER_t*)&buf[13]; fu_hdr->E = 0; fu_hdr->R = 0; fu_hdr->S = 0; fu_hdr->TYPE = nalu->nal_unit_type; memcpy(&buf[14], nalu->nalu_pbuf + i * MTU_SIZE + 1, MTU_SIZE); bytes = MTU_SIZE + 14; sendto(connfd, buf, bytes, 0, (SA *)&peeraddr, sizeof(peeraddr)); } } } /* * Single NAL Unit Packet: Contains only a single NAL unit in the payload. * The NAL header type field will be equal to the original NAL unit type. */ else { printf("***********\n"); ts_current = ts_current + ts_incremental; rtp_hdr->timestamp = htonl(ts_current); rtp_hdr->marker = 1; rtp_hdr->seq_no = htons(seq_num ++); nalu_hdr = (NALU_HEADER_t *)&buf[12]; nalu_hdr->F = nalu->forbidden_zero_bit; nalu_hdr->NRI = nalu->nal_ref_idc >> 5; nalu_hdr->TYPE = nalu->nal_unit_type; memcpy(&buf[13], nalu->nalu_pbuf + 1, nalu->nalu_size - 1); bytes = nalu->nalu_size + 12 ; sendto(connfd, buf, bytes, 0, (SA *)&peeraddr, sizeof(peeraddr)); } } cleanup: printf("ending prog ... \n"); close(connfd); if (nalu) { NALU_delete(nalu); } if (pNalu) { free(pNalu); } if (videoFile) { fclose(videoFile); } return 0; }