├── .gitignore ├── Makefile ├── README.md ├── rtsp_server.h ├── sample_venc └── sample_venc.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Hisilicon Hi3516 sample Makefile 2 | 3 | include ../Makefile.param 4 | #ifeq ($(SAMPLE_PARAM_FILE), ) 5 | # SAMPLE_PARAM_FILE:=../Makefile.param 6 | # include $(SAMPLE_PARAM_FILE) 7 | #endif 8 | 9 | # target source 10 | SRC := $(wildcard *.c) 11 | OBJ := $(SRC:%.c=%.o) 12 | 13 | TARGET := $(OBJ:%.o=%) 14 | .PHONY : clean all 15 | 16 | all: $(TARGET) 17 | 18 | MPI_LIBS := $(REL_LIB)/libmpi.a 19 | 20 | $(TARGET):%:%.o $(COMM_OBJ) 21 | $(CC) $(CFLAGS) -lpthread -lm -o $@ $^ $(MPI_LIBS) $(AUDIO_LIBA) $(SENSOR_LIBS) 22 | 23 | clean: 24 | @rm -f $(TARGET) 25 | @rm -f $(OBJ) 26 | @rm -f $(COMM_OBJ) 27 | 28 | cleanstream: 29 | @rm -f *.h264 30 | @rm -f *.jpg 31 | @rm -f *.mjp 32 | @rm -f *.mp4 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vencrtsp 2 | hi3518开发板发送rtsp传输协议。 3 | -------------------------------------------------------------------------------- /rtsp_server.h: -------------------------------------------------------------------------------- 1 | #ifndef RTSP_SERVER_H 2 | #define RTSP_SERVER_H 3 | 4 | #if !defined(WIN32) 5 | #define __PACKED__ __attribute__ ((__packed__)) 6 | #else 7 | #define __PACKED__ 8 | #endif 9 | 10 | typedef enum 11 | { 12 | RTSP_VIDEO=0, 13 | RTSP_VIDEOSUB=1, 14 | RTSP_AUDIO=2, 15 | RTSP_YUV422=3, 16 | RTSP_RGB=4, 17 | RTSP_VIDEOPS=5, 18 | RTSP_VIDEOSUBPS=6 19 | }enRTSP_MonBlockType; 20 | 21 | struct _RTP_FIXED_HEADER 22 | { 23 | /**//* byte 0 */ 24 | unsigned char csrc_len:4; /**//* expect 0 */ 25 | unsigned char extension:1; /**//* expect 1, see RTP_OP below */ 26 | unsigned char padding:1; /**//* expect 0 */ 27 | unsigned char version:2; /**//* expect 2 */ 28 | /**//* byte 1 */ 29 | unsigned char payload:7; /**//* RTP_PAYLOAD_RTSP */ 30 | unsigned char marker:1; /**//* expect 1 */ 31 | /**//* bytes 2, 3 */ 32 | unsigned short seq_no; 33 | /**//* bytes 4-7 */ 34 | unsigned long timestamp; 35 | /**//* bytes 8-11 */ 36 | unsigned long ssrc; /**//* stream number is used here. */ 37 | } __PACKED__; 38 | 39 | typedef struct _RTP_FIXED_HEADER RTP_FIXED_HEADER; 40 | 41 | struct _NALU_HEADER 42 | { 43 | //byte 0 44 | unsigned char TYPE:5; 45 | unsigned char NRI:2; 46 | unsigned char F:1; 47 | 48 | }__PACKED__; /**//* 1 BYTES */ 49 | 50 | typedef struct _NALU_HEADER NALU_HEADER; 51 | 52 | struct _FU_INDICATOR 53 | { 54 | //byte 0 55 | unsigned char TYPE:5; 56 | unsigned char NRI:2; 57 | unsigned char F:1; 58 | 59 | }__PACKED__; /**//* 1 BYTES */ 60 | 61 | typedef struct _FU_INDICATOR FU_INDICATOR; 62 | 63 | struct _FU_HEADER 64 | { 65 | //byte 0 66 | unsigned char TYPE:5; 67 | unsigned char R:1; 68 | unsigned char E:1; 69 | unsigned char S:1; 70 | } __PACKED__; /**//* 1 BYTES */ 71 | typedef struct _FU_HEADER FU_HEADER; 72 | 73 | struct _AU_HEADER 74 | { 75 | //byte 0, 1 76 | unsigned short au_len; 77 | //byte 2,3 78 | unsigned short frm_len:13; 79 | unsigned char au_index:3; 80 | } __PACKED__; /**//* 1 BYTES */ 81 | typedef struct _AU_HEADER AU_HEADER; 82 | 83 | 84 | void InitRtspServer(); 85 | int AddFrameToRtspBuf(int nChanNum,enRTSP_MonBlockType eType, char * pData, unsigned int nSize, unsigned int nVidFrmNum,int bIFrm); 86 | 87 | 88 | 89 | 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /sample_venc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaurenLuoYun/vencrtsp/bfc4ed18699b45336b93f124cd76f59bea031445/sample_venc -------------------------------------------------------------------------------- /sample_venc.c: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | #if __cplusplus 3 | extern "C"{ 4 | #endif 5 | #endif /* End of #ifdef __cplusplus */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "rtsp_server.h" 29 | #include "sample_comm.h" 30 | 31 | #define nalu_sent_len 14000 32 | //#define nalu_sent_len 1400 33 | #define RTP_H264 96 34 | #define MAX_CHAN 8 35 | #define RTP_AUDIO 97 36 | #define MAX_RTSP_CLIENT 4 37 | #define RTSP_SERVER_PORT 554 38 | #define RTSP_RECV_SIZE 1024 39 | #define RTSP_MAX_VID (640*1024) 40 | #define RTSP_MAX_AUD (15*1024) 41 | 42 | #define AU_HEADER_SIZE 4 43 | #define PARAM_STRING_MAX 100 44 | 45 | static SAMPLE_VENC_GETSTREAM_PARA_S gs_stPara; 46 | static pthread_t gs_VencPid; 47 | 48 | typedef unsigned short u_int16_t; 49 | typedef unsigned char u_int8_t; 50 | typedef u_int16_t portNumBits; 51 | typedef u_int32_t netAddressBits; 52 | typedef long long _int64; 53 | #ifndef FALSE 54 | #define FALSE 0 55 | #endif 56 | #ifndef TRUE 57 | #define TRUE 1 58 | #endif 59 | #define AUDIO_RATE 8000 60 | #define PACKET_BUFFER_END (unsigned int)0x00000000 61 | 62 | 63 | typedef struct 64 | { 65 | int startblock;//代表开始文件块号 66 | int endblock;//代表结束文件块号 67 | int BlockFileNum;//代表录像段数 68 | 69 | }IDXFILEHEAD_INFO;//.IDX文件的头信息 70 | 71 | typedef struct 72 | { 73 | _int64 starttime;//代表开始shijian 74 | _int64 endtime;//代表结束shijian 75 | int startblock;//代表开始文件块号 76 | int endblock;//代表结束文件块号 77 | int stampnum;//代表时间戳数量 78 | }IDXFILEBLOCK_INFO;//.IDX文件段信息 79 | 80 | typedef struct 81 | { 82 | int blockindex;//代表所在文件块号 83 | int pos;//代表该时间戳在文件块的位置 84 | _int64 time;//代表时间戳时间戳的时间点 85 | }IDXSTAMP_INFO;//.IDX文件的时间戳信息 86 | 87 | typedef struct 88 | { 89 | char filename[150];//代表所在文件块号 90 | int pos;//代表该时间戳在文件块的位置 91 | _int64 time;//代表时间戳时间戳的时间点 92 | }FILESTAMP_INFO;//.IDX文件的时间戳信息 93 | 94 | typedef struct 95 | { 96 | char channelid[9]; 97 | _int64 starttime;//代表开始shijian 98 | _int64 endtime;//代表结束shijian 99 | _int64 session; 100 | int type; //类型 101 | int encodetype;//编码格式; 102 | }FIND_INFO;//.IDX文件的时间戳信息 103 | 104 | typedef enum 105 | { 106 | RTP_UDP, 107 | RTP_TCP, 108 | RAW_UDP 109 | }StreamingMode; 110 | 111 | 112 | RTP_FIXED_HEADER *rtp_hdr; 113 | NALU_HEADER *nalu_hdr; 114 | FU_INDICATOR *fu_ind; 115 | FU_HEADER *fu_hdr; 116 | AU_HEADER *au_hdr; 117 | 118 | 119 | extern char g_rtp_playload[20];//ĬÈÏG726-32 120 | extern int g_audio_rate;//ĬÈÏ8000 121 | 122 | typedef enum 123 | { 124 | RTSP_IDLE = 0, 125 | RTSP_CONNECTED = 1, 126 | RTSP_SENDING = 2, 127 | }RTSP_STATUS; 128 | 129 | typedef struct 130 | { 131 | int nVidLen; 132 | int nAudLen; 133 | int bIsIFrm; 134 | int bWaitIFrm; 135 | int bIsFree; 136 | char vidBuf[RTSP_MAX_VID]; 137 | char audBuf[RTSP_MAX_AUD]; 138 | }RTSP_PACK; 139 | 140 | typedef struct 141 | { 142 | int index; 143 | int socket; 144 | int reqchn; 145 | int seqnum; 146 | int seqnum2; 147 | unsigned int tsvid; 148 | unsigned int tsaud; 149 | int status; 150 | int sessionid; 151 | int rtpport[2]; 152 | int rtcpport; 153 | char IP[20]; 154 | char urlPre[PARAM_STRING_MAX]; 155 | }RTSP_CLIENT; 156 | 157 | typedef struct 158 | { 159 | int vidLen; 160 | int audLen; 161 | int nFrameID; 162 | char vidBuf[RTSP_MAX_VID]; 163 | char audBuf[RTSP_MAX_AUD]; 164 | }FRAME_PACK; 165 | typedef struct 166 | { 167 | int startcodeprefix_len; //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested) 168 | unsigned len; //! Length of the NAL unit (Excluding the start code, which does not belong to the NALU) 169 | unsigned max_size; //! Nal Unit Buffer size 170 | int forbidden_bit; //! should be always FALSE 171 | int nal_reference_idc; //! NALU_PRIORITY_xxxx 172 | int nal_unit_type; //! NALU_TYPE_xxxx 173 | char *buf; //! contains the first byte followed by the EBSP 174 | unsigned short lost_packets; //! true, if packet loss is detected 175 | } NALU_t; 176 | 177 | //static bool flag = true; 178 | RTP_FIXED_HEADER *rtp_hdr; 179 | 180 | NALU_HEADER *nalu_hdr; 181 | FU_INDICATOR *fu_ind; 182 | FU_HEADER *fu_hdr; 183 | 184 | FRAME_PACK g_FrmPack[MAX_CHAN]; 185 | RTSP_PACK g_rtpPack[MAX_CHAN]; 186 | RTSP_CLIENT g_rtspClients[MAX_RTSP_CLIENT]; 187 | 188 | int g_nSendDataChn = -1; 189 | pthread_mutex_t g_mutex; 190 | pthread_cond_t g_cond; 191 | pthread_mutex_t g_sendmutex; 192 | 193 | pthread_t g_SendDataThreadId = 0; 194 | //HAL_CLIENT_HANDLE hMainStreamClient = NULL,hSubStreamClient = NULL,hAudioClient = NULL; 195 | char g_rtp_playload[20]; 196 | int g_audio_rate = 8000; 197 | VIDEO_NORM_E gs_enNorm = VIDEO_ENCODING_MODE_NTSC;//30fps 198 | int g_nframerate; 199 | //VIDEO_NORM_E gs_enNorm = VIDEO_ENCODING_MODE_PAL;//15fps 200 | //int g_nframerate = 15; 201 | int exitok = 0; 202 | 203 | int udpfd; 204 | 205 | 206 | 207 | 208 | static char const* dateHeader() 209 | { 210 | static char buf[200]; 211 | #if !defined(_WIN32_WCE) 212 | time_t tt = time(NULL); 213 | strftime(buf, sizeof buf, "Date: %a, %b %d %Y %H:%M:%S GMT\r\n", gmtime(&tt)); 214 | #endif 215 | 216 | return buf; 217 | } 218 | static char* GetLocalIP(int sock) 219 | { 220 | struct ifreq ifreq; 221 | struct sockaddr_in *sin; 222 | char * LocalIP = malloc(20); 223 | strcpy(ifreq.ifr_name,"eth0"); 224 | if (!(ioctl (sock, SIOCGIFADDR,&ifreq))) 225 | { 226 | sin = (struct sockaddr_in *)&ifreq.ifr_addr; 227 | sin->sin_family = AF_INET; 228 | strcpy(LocalIP,inet_ntoa(sin->sin_addr)); 229 | //inet_ntop(AF_INET, &sin->sin_addr,LocalIP, 16); 230 | } 231 | printf("--------------------------------------------%s\n",LocalIP); 232 | return LocalIP; 233 | } 234 | 235 | char* strDupSize(char const* str) 236 | { 237 | if (str == NULL) return NULL; 238 | size_t len = strlen(str) + 1; 239 | char* copy = malloc(len); 240 | 241 | return copy; 242 | } 243 | int ParseRequestString(char const* reqStr, 244 | unsigned reqStrSize, 245 | char* resultCmdName, 246 | unsigned resultCmdNameMaxSize, 247 | char* resultURLPreSuffix, 248 | unsigned resultURLPreSuffixMaxSize, 249 | char* resultURLSuffix, 250 | unsigned resultURLSuffixMaxSize, 251 | char* resultCSeq, 252 | unsigned resultCSeqMaxSize) 253 | { 254 | // This parser is currently rather dumb; it should be made smarter ##### 255 | 256 | // Read everything up to the first space as the command name: 257 | int parseSucceeded = FALSE; 258 | unsigned i; 259 | for (i = 0; i < resultCmdNameMaxSize-1 && i < reqStrSize; ++i) { 260 | char c = reqStr[i]; 261 | if (c == ' ' || c == '\t') { 262 | parseSucceeded = TRUE; 263 | break; 264 | } 265 | 266 | resultCmdName[i] = c; 267 | } 268 | resultCmdName[i] = '\0'; 269 | if (!parseSucceeded) return FALSE; 270 | 271 | // Skip over the prefix of any "rtsp://" or "rtsp:/" URL that follows: 272 | unsigned j = i+1; 273 | while (j < reqStrSize && (reqStr[j] == ' ' || reqStr[j] == '\t')) ++j; // skip over any additional white space 274 | for (j = i+1; j < reqStrSize-8; ++j) { 275 | if ((reqStr[j] == 'r' || reqStr[j] == 'R') 276 | && (reqStr[j+1] == 't' || reqStr[j+1] == 'T') 277 | && (reqStr[j+2] == 's' || reqStr[j+2] == 'S') 278 | && (reqStr[j+3] == 'p' || reqStr[j+3] == 'P') 279 | && reqStr[j+4] == ':' && reqStr[j+5] == '/') { 280 | j += 6; 281 | if (reqStr[j] == '/') { 282 | // This is a "rtsp://" URL; skip over the host:port part that follows: 283 | ++j; 284 | while (j < reqStrSize && reqStr[j] != '/' && reqStr[j] != ' ') ++j; 285 | } else { 286 | // This is a "rtsp:/" URL; back up to the "/": 287 | --j; 288 | } 289 | i = j; 290 | break; 291 | } 292 | } 293 | 294 | // Look for the URL suffix (before the following "RTSP/"): 295 | parseSucceeded = FALSE; 296 | unsigned k; 297 | for (k = i+1; k < reqStrSize-5; ++k) { 298 | if (reqStr[k] == 'R' && reqStr[k+1] == 'T' && 299 | reqStr[k+2] == 'S' && reqStr[k+3] == 'P' && reqStr[k+4] == '/') { 300 | while (--k >= i && reqStr[k] == ' ') {} // go back over all spaces before "RTSP/" 301 | unsigned k1 = k; 302 | while (k1 > i && reqStr[k1] != '/' && reqStr[k1] != ' ') --k1; 303 | // the URL suffix comes from [k1+1,k] 304 | 305 | // Copy "resultURLSuffix": 306 | if (k - k1 + 1 > resultURLSuffixMaxSize) return FALSE; // there's no room 307 | unsigned n = 0, k2 = k1+1; 308 | while (k2 <= k) resultURLSuffix[n++] = reqStr[k2++]; 309 | resultURLSuffix[n] = '\0'; 310 | 311 | // Also look for the URL 'pre-suffix' before this: 312 | unsigned k3 = --k1; 313 | while (k3 > i && reqStr[k3] != '/' && reqStr[k3] != ' ') --k3; 314 | // the URL pre-suffix comes from [k3+1,k1] 315 | 316 | // Copy "resultURLPreSuffix": 317 | if (k1 - k3 + 1 > resultURLPreSuffixMaxSize) return FALSE; // there's no room 318 | n = 0; k2 = k3+1; 319 | while (k2 <= k1) resultURLPreSuffix[n++] = reqStr[k2++]; 320 | resultURLPreSuffix[n] = '\0'; 321 | 322 | i = k + 7; // to go past " RTSP/" 323 | parseSucceeded = TRUE; 324 | break; 325 | } 326 | } 327 | if (!parseSucceeded) return FALSE; 328 | 329 | // Look for "CSeq:", skip whitespace, 330 | // then read everything up to the next \r or \n as 'CSeq': 331 | parseSucceeded = FALSE; 332 | for (j = i; j < reqStrSize-5; ++j) { 333 | if (reqStr[j] == 'C' && reqStr[j+1] == 'S' && reqStr[j+2] == 'e' && 334 | reqStr[j+3] == 'q' && reqStr[j+4] == ':') { 335 | j += 5; 336 | unsigned n; 337 | while (j < reqStrSize && (reqStr[j] == ' ' || reqStr[j] == '\t')) ++j; 338 | for (n = 0; n < resultCSeqMaxSize-1 && j < reqStrSize; ++n,++j) { 339 | char c = reqStr[j]; 340 | if (c == '\r' || c == '\n') { 341 | parseSucceeded = TRUE; 342 | break; 343 | } 344 | 345 | resultCSeq[n] = c; 346 | } 347 | resultCSeq[n] = '\0'; 348 | break; 349 | } 350 | } 351 | if (!parseSucceeded) return FALSE; 352 | 353 | return TRUE; 354 | } 355 | 356 | int OptionAnswer(char *cseq, int sock) 357 | { 358 | if (sock != 0) 359 | { 360 | char buf[1024]; 361 | memset(buf,0,1024); 362 | char *pTemp = buf; 363 | pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sPublic: %s\r\n\r\n", 364 | cseq,dateHeader(),"OPTIONS,DESCRIBE,SETUP,PLAY,PAUSE,TEARDOWN"); 365 | 366 | int reg = send(sock, buf,strlen(buf),0); 367 | if(reg <= 0) 368 | { 369 | return FALSE; 370 | } 371 | else 372 | { 373 | printf(">>>>>%s\n",buf); 374 | } 375 | return TRUE; 376 | } 377 | return FALSE; 378 | } 379 | 380 | int DescribeAnswer(char *cseq,int sock,char * urlSuffix,char* recvbuf) 381 | { 382 | if (sock != 0) 383 | { 384 | char sdpMsg[1024]; 385 | char buf[2048]; 386 | memset(buf,0,2048); 387 | memset(sdpMsg,0,1024); 388 | char*localip; 389 | localip = GetLocalIP(sock); 390 | 391 | char *pTemp = buf; 392 | pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n",cseq); 393 | pTemp += sprintf(pTemp,"%s",dateHeader()); 394 | pTemp += sprintf(pTemp,"Content-Type: application/sdp\r\n"); 395 | 396 | //TODO °ÑһЩ¹Ì¶šÖµžÄΪ¶¯Ì¬Öµ 397 | char *pTemp2 = sdpMsg; 398 | pTemp2 += sprintf(pTemp2,"v=0\r\n"); 399 | pTemp2 += sprintf(pTemp2,"o=StreamingServer 3331435948 1116907222000 IN IP4 %s\r\n",localip); 400 | pTemp2 += sprintf(pTemp2,"s=H.264\r\n"); 401 | pTemp2 += sprintf(pTemp2,"c=IN IP4 0.0.0.0\r\n"); 402 | pTemp2 += sprintf(pTemp2,"t=0 0\r\n"); 403 | pTemp2 += sprintf(pTemp2,"a=control:*\r\n"); 404 | 405 | /*ÊÓÆµÃœÌåÃèÊö*/ 406 | /*H264 TrackID=0 RTP_PT 96*/ 407 | pTemp2 += sprintf(pTemp2,"m=video 0 RTP/AVP 96\r\n"); 408 | pTemp2 += sprintf(pTemp2,"a=control:trackID=0\r\n"); 409 | pTemp2 += sprintf(pTemp2,"a=rtpmap:96 H264/90000\r\n"); 410 | pTemp2 += sprintf(pTemp2,"a=fmtp:96 packetization-mode=1; sprop-parameter-sets=%s\r\n", "AAABBCCC"); 411 | #if 1 412 | /*ÒôƵÜÌåÃèÊö*/ 413 | /*G726*/ 414 | /*TODO ÒôƵ*/ 415 | pTemp2 += sprintf(pTemp2,"m=audio 0 RTP/AVP 97\r\n"); 416 | pTemp2 += sprintf(pTemp2,"a=control:trackID=1\r\n"); 417 | if(strcmp(g_rtp_playload,"AAC")==0) 418 | { 419 | pTemp2 += sprintf(pTemp2,"a=rtpmap:97 MPEG4-GENERIC/%d/2\r\n",16000); 420 | pTemp2 += sprintf(pTemp2,"a=fmtp:97 streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config=1410\r\n"); 421 | } 422 | else 423 | { 424 | pTemp2 += sprintf(pTemp2,"a=rtpmap:97 G726-32/%d/1\r\n",8000); 425 | pTemp2 += sprintf(pTemp2,"a=fmtp:97 packetization-mode=1\r\n"); 426 | } 427 | #endif 428 | pTemp += sprintf(pTemp,"Content-length: %d\r\n", strlen(sdpMsg)); 429 | pTemp += sprintf(pTemp,"Content-Base: rtsp://%s/%s/\r\n\r\n",localip,urlSuffix); 430 | 431 | //printf("mem ready\n"); 432 | strcat(pTemp, sdpMsg); 433 | free(localip); 434 | //printf("Describe ready sent\n"); 435 | int re = send(sock, buf, strlen(buf),0); 436 | if(re <= 0) 437 | { 438 | return FALSE; 439 | } 440 | else 441 | { 442 | printf(">>>>>%s\n",buf); 443 | } 444 | } 445 | 446 | return TRUE; 447 | } 448 | void ParseTransportHeader(char const* buf, 449 | StreamingMode* streamingMode, 450 | char**streamingModeString, 451 | char**destinationAddressStr, 452 | u_int8_t* destinationTTL, 453 | portNumBits* clientRTPPortNum, // if UDP 454 | portNumBits* clientRTCPPortNum, // if UDP 455 | unsigned char* rtpChannelId, // if TCP 456 | unsigned char* rtcpChannelId // if TCP 457 | ) 458 | { 459 | // Initialize the result parameters to default values: 460 | *streamingMode = RTP_UDP; 461 | *streamingModeString = NULL; 462 | *destinationAddressStr = NULL; 463 | *destinationTTL = 255; 464 | *clientRTPPortNum = 0; 465 | *clientRTCPPortNum = 1; 466 | *rtpChannelId = *rtcpChannelId = 0xFF; 467 | 468 | portNumBits p1, p2; 469 | unsigned ttl, rtpCid, rtcpCid; 470 | 471 | // First, find "Transport:" 472 | while (1) { 473 | if (*buf == '\0') return; // not found 474 | if (strncasecmp(buf, "Transport: ", 11) == 0) break; 475 | ++buf; 476 | } 477 | 478 | // Then, run through each of the fields, looking for ones we handle: 479 | char const* fields = buf + 11; 480 | char* field = strDupSize(fields); 481 | while (sscanf(fields, "%[^;]", field) == 1) { 482 | if (strcmp(field, "RTP/AVP/TCP") == 0) { 483 | *streamingMode = RTP_TCP; 484 | } else if (strcmp(field, "RAW/RAW/UDP") == 0 || 485 | strcmp(field, "MP2T/H2221/UDP") == 0) { 486 | *streamingMode = RAW_UDP; 487 | //*streamingModeString = strDup(field); 488 | } else if (strncasecmp(field, "destination=", 12) == 0) 489 | { 490 | //delete[] destinationAddressStr; 491 | free(destinationAddressStr); 492 | //destinationAddressStr = strDup(field+12); 493 | } else if (sscanf(field, "ttl%u", &ttl) == 1) { 494 | destinationTTL = (u_int8_t)ttl; 495 | } else if (sscanf(field, "client_port=%hu-%hu", &p1, &p2) == 2) { 496 | *clientRTPPortNum = p1; 497 | *clientRTCPPortNum = p2; 498 | } else if (sscanf(field, "client_port=%hu", &p1) == 1) { 499 | *clientRTPPortNum = p1; 500 | *clientRTCPPortNum = streamingMode == RAW_UDP ? 0 : p1 + 1; 501 | } else if (sscanf(field, "interleaved=%u-%u", &rtpCid, &rtcpCid) == 2) { 502 | *rtpChannelId = (unsigned char)rtpCid; 503 | *rtcpChannelId = (unsigned char)rtcpCid; 504 | } 505 | 506 | fields += strlen(field); 507 | while (*fields == ';') ++fields; // skip over separating ';' chars 508 | if (*fields == '\0' || *fields == '\r' || *fields == '\n') break; 509 | } 510 | free(field); 511 | } 512 | 513 | 514 | int SetupAnswer(char *cseq,int sock,int SessionId,char * urlSuffix,char* recvbuf,int* rtpport, int* rtcpport) 515 | { 516 | if (sock != 0) 517 | { 518 | char buf[1024]; 519 | memset(buf,0,1024); 520 | 521 | StreamingMode streamingMode; 522 | char* streamingModeString; // set when RAW_UDP streaming is specified 523 | char* clientsDestinationAddressStr; 524 | u_int8_t clientsDestinationTTL; 525 | portNumBits clientRTPPortNum, clientRTCPPortNum; 526 | unsigned char rtpChannelId, rtcpChannelId; 527 | ParseTransportHeader(recvbuf,&streamingMode, &streamingModeString, 528 | &clientsDestinationAddressStr, &clientsDestinationTTL, 529 | &clientRTPPortNum, &clientRTCPPortNum, 530 | &rtpChannelId, &rtcpChannelId); 531 | 532 | //Port clientRTPPort(clientRTPPortNum); 533 | //Port clientRTCPPort(clientRTCPPortNum); 534 | *rtpport = clientRTPPortNum; 535 | *rtcpport = clientRTCPPortNum; 536 | 537 | char *pTemp = buf; 538 | char*localip; 539 | localip = GetLocalIP(sock); 540 | pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sTransport: RTP/AVP;unicast;destination=%s;client_port=%d-%d;server_port=%d-%d\r\nSession: %d\r\n\r\n", 541 | cseq,dateHeader(),localip, 542 | ntohs(htons(clientRTPPortNum)), 543 | ntohs(htons(clientRTCPPortNum)), 544 | ntohs(2000), 545 | ntohs(2001), 546 | SessionId); 547 | 548 | free(localip); 549 | int reg = send(sock, buf,strlen(buf),0); 550 | if(reg <= 0) 551 | { 552 | return FALSE; 553 | } 554 | else 555 | { 556 | printf(">>>>>%s",buf); 557 | } 558 | return TRUE; 559 | } 560 | return FALSE; 561 | } 562 | 563 | int PlayAnswer(char *cseq, int sock,int SessionId,char* urlPre,char* recvbuf) 564 | { 565 | if (sock != 0) 566 | { 567 | char buf[1024]; 568 | memset(buf,0,1024); 569 | char *pTemp = buf; 570 | char*localip; 571 | localip = GetLocalIP(sock); 572 | pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sRange: npt=0.000-\r\nSession: %d\r\nRTP-Info: url=rtsp://%s/%s;seq=0\r\n\r\n", 573 | cseq,dateHeader(),SessionId,localip,urlPre); 574 | 575 | free(localip); 576 | 577 | int reg = send(sock, buf,strlen(buf),0); 578 | if(reg <= 0) 579 | { 580 | return FALSE; 581 | } 582 | else 583 | { 584 | printf(">>>>>%s",buf); 585 | } 586 | return TRUE; 587 | } 588 | return FALSE; 589 | } 590 | 591 | int PauseAnswer(char *cseq,int sock,char *recvbuf) 592 | { 593 | if (sock != 0) 594 | { 595 | char buf[1024]; 596 | memset(buf,0,1024); 597 | char *pTemp = buf; 598 | pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%s\r\n\r\n", 599 | cseq,dateHeader()); 600 | 601 | int reg = send(sock, buf,strlen(buf),0); 602 | if(reg <= 0) 603 | { 604 | return FALSE; 605 | } 606 | else 607 | { 608 | printf(">>>>>%s",buf); 609 | } 610 | return TRUE; 611 | } 612 | return FALSE; 613 | } 614 | 615 | int TeardownAnswer(char *cseq,int sock,int SessionId,char *recvbuf) 616 | { 617 | if (sock != 0) 618 | { 619 | char buf[1024]; 620 | memset(buf,0,1024); 621 | char *pTemp = buf; 622 | pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sSession: %d\r\n\r\n", 623 | cseq,dateHeader(),SessionId); 624 | 625 | int reg = send(sock, buf,strlen(buf),0); 626 | if(reg <= 0) 627 | { 628 | return FALSE; 629 | } 630 | else 631 | { 632 | printf(">>>>>%s",buf); 633 | } 634 | return TRUE; 635 | } 636 | return FALSE; 637 | } 638 | void * RtspClientMsg(void*pParam) 639 | { 640 | pthread_detach(pthread_self()); 641 | int nRes; 642 | char pRecvBuf[RTSP_RECV_SIZE]; 643 | RTSP_CLIENT * pClient = (RTSP_CLIENT*)pParam; 644 | memset(pRecvBuf,0,sizeof(pRecvBuf)); 645 | printf("RTSP:-----Create Client %s\n",pClient->IP); 646 | while(pClient->status != RTSP_IDLE) 647 | { 648 | nRes = recv(pClient->socket, pRecvBuf, RTSP_RECV_SIZE,0); 649 | //printf("-------------------%d\n",nRes); 650 | if(nRes < 1) 651 | { 652 | //usleep(1000); 653 | printf("RTSP:Recv Error--- %d\n",nRes); 654 | g_rtspClients[pClient->index].status = RTSP_IDLE; 655 | g_rtspClients[pClient->index].seqnum = 0; 656 | g_rtspClients[pClient->index].tsvid = 0; 657 | g_rtspClients[pClient->index].tsaud = 0; 658 | close(pClient->socket); 659 | break; 660 | } 661 | char cmdName[PARAM_STRING_MAX]; 662 | char urlPreSuffix[PARAM_STRING_MAX]; 663 | char urlSuffix[PARAM_STRING_MAX]; 664 | char cseq[PARAM_STRING_MAX]; 665 | 666 | ParseRequestString(pRecvBuf,nRes,cmdName,sizeof(cmdName),urlPreSuffix,sizeof(urlPreSuffix), 667 | urlSuffix,sizeof(urlSuffix),cseq,sizeof(cseq)); 668 | 669 | char *p = pRecvBuf; 670 | 671 | printf("<<<<<%s\n",p); 672 | 673 | //printf("\--------------------------\n"); 674 | //printf("%s %s\n",urlPreSuffix,urlSuffix); 675 | 676 | if(strstr(cmdName, "OPTIONS")) 677 | { 678 | OptionAnswer(cseq,pClient->socket); 679 | } 680 | else if(strstr(cmdName, "DESCRIBE")) 681 | { 682 | DescribeAnswer(cseq,pClient->socket,urlSuffix,p); 683 | //printf("-----------------------------DescribeAnswer %s %s\n", 684 | // urlPreSuffix,urlSuffix); 685 | } 686 | else if(strstr(cmdName, "SETUP")) 687 | { 688 | int rtpport,rtcpport; 689 | int trackID=0; 690 | SetupAnswer(cseq,pClient->socket,pClient->sessionid,urlPreSuffix,p,&rtpport,&rtcpport); 691 | 692 | sscanf(urlSuffix, "trackID=%u", &trackID); 693 | //printf("----------------------------------------------TrackId %d\n",trackID); 694 | if(trackID<0 || trackID>=2)trackID=0; 695 | g_rtspClients[pClient->index].rtpport[trackID] = rtpport; 696 | g_rtspClients[pClient->index].rtcpport= rtcpport; 697 | g_rtspClients[pClient->index].reqchn = atoi(urlPreSuffix); 698 | if(strlen(urlPreSuffix)<100) 699 | strcpy(g_rtspClients[pClient->index].urlPre,urlPreSuffix); 700 | //printf("-----------------------------SetupAnswer %s-%d-%d\n", 701 | // urlPreSuffix,g_rtspClients[pClient->index].reqchn,rtpport); 702 | } 703 | else if(strstr(cmdName, "PLAY")) 704 | { 705 | PlayAnswer(cseq,pClient->socket,pClient->sessionid,g_rtspClients[pClient->index].urlPre,p); 706 | g_rtspClients[pClient->index].status = RTSP_SENDING; 707 | printf("Start Play\n",pClient->index); 708 | //printf("-----------------------------PlayAnswer %d %d\n",pClient->index); 709 | //usleep(100); 710 | } 711 | else if(strstr(cmdName, "PAUSE")) 712 | { 713 | PauseAnswer(cseq,pClient->socket,p); 714 | } 715 | else if(strstr(cmdName, "TEARDOWN")) 716 | { 717 | TeardownAnswer(cseq,pClient->socket,pClient->sessionid,p); 718 | g_rtspClients[pClient->index].status = RTSP_IDLE; 719 | g_rtspClients[pClient->index].seqnum = 0; 720 | g_rtspClients[pClient->index].tsvid = 0; 721 | g_rtspClients[pClient->index].tsaud = 0; 722 | close(pClient->socket); 723 | } 724 | if(exitok){ exitok++;return NULL; } 725 | } 726 | printf("RTSP:-----Exit Client %s\n",pClient->IP); 727 | return NULL; 728 | } 729 | 730 | void * RtspServerListen(void*pParam) 731 | { 732 | int s32Socket; 733 | struct sockaddr_in servaddr; 734 | int s32CSocket; 735 | int s32Rtn; 736 | int s32Socket_opt_value = 1; 737 | int nAddrLen; 738 | struct sockaddr_in addrAccept; 739 | int bResult; 740 | 741 | memset(&servaddr, 0, sizeof(servaddr)); 742 | servaddr.sin_family = AF_INET; 743 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 744 | servaddr.sin_port = htons(RTSP_SERVER_PORT); 745 | 746 | s32Socket = socket(AF_INET, SOCK_STREAM, 0); 747 | 748 | if (setsockopt(s32Socket ,SOL_SOCKET,SO_REUSEADDR,&s32Socket_opt_value,sizeof(int)) == -1) 749 | { 750 | return (void *)(-1); 751 | } 752 | s32Rtn = bind(s32Socket, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in)); 753 | if(s32Rtn < 0) 754 | { 755 | return (void *)(-2); 756 | } 757 | 758 | s32Rtn = listen(s32Socket, 50); /*50,×îŽóµÄÁ¬œÓÊý*/ 759 | if(s32Rtn < 0) 760 | { 761 | 762 | return (void *)(-2); 763 | } 764 | 765 | 766 | nAddrLen = sizeof(struct sockaddr_in); 767 | int nSessionId = 1000; 768 | while ((s32CSocket = accept(s32Socket, (struct sockaddr*)&addrAccept, &nAddrLen)) >= 0) 769 | { 770 | printf("<<<=MAX_CHAN ) 878 | { 879 | continue; 880 | } 881 | nAvFrmLen = buflen; 882 | //printf("%d\n",nAvFrmLen); 883 | //nAvFrmLen = vStreamInfo.dwSize ;//Streamlen 884 | struct sockaddr_in server; 885 | server.sin_family=AF_INET; 886 | server.sin_port=htons(g_rtspClients[is].rtpport[0]); 887 | server.sin_addr.s_addr=inet_addr(g_rtspClients[is].IP); 888 | int bytes=0; 889 | unsigned int timestamp_increse=0; 890 | 891 | //timeing in = out,15fps in,so same f out 892 | //if(VIDEO_ENCODING_MODE_PAL == gs_enNorm)g_nframerate = 15; 893 | //else if(VIDEO_ENCODING_MODE_NTSC == gs_enNorm)g_nframerate = 30; 894 | if(VIDEO_ENCODING_MODE_PAL == gs_enNorm)g_nframerate = 16; 895 | else if(VIDEO_ENCODING_MODE_NTSC == gs_enNorm)g_nframerate = 32; 896 | 897 | //if(VIDEO_ENCODING_MODE_PAL == gs_enNorm)timestamp_increse=5625;//90000/16 898 | //else if(VIDEO_ENCODING_MODE_NTSC == gs_enNorm)timestamp_increse=2813;//90000/32 899 | 900 | timestamp_increse=(unsigned int)(90000.0 / g_nframerate); 901 | //sendto(udpfd, buffer, nAvFrmLen, 0, (struct sockaddr *)&server,sizeof(server)); 902 | 903 | 904 | 905 | //rtp¹Ì¶¨°üÍ·£¬Îª12×Ö½Ú,¸Ã¾ä½«sendbuf[0]µÄµØÖ·¸³¸ørtp_hdr£¬ 906 | //ÒÔºó¶Ôrtp_hdrµÄдÈë²Ù×÷½«Ö±½ÓдÈësendbuf¡£ 907 | rtp_hdr =(RTP_FIXED_HEADER*)&sendbuf[0]; 908 | //ÉèÖÃRTP HEADER£¬ 909 | rtp_hdr->payload = RTP_H264; //¸ºÔØÀàÐͺţ¬ 910 | rtp_hdr->version = 2; //°æ±¾ºÅ£¬´Ë°æ±¾¹Ì¶¨Îª2 911 | rtp_hdr->marker = 0; //±ê־룬ÓɾßÌåЭÒ鹿¶¨ÆäÖµ¡£ 912 | rtp_hdr->ssrc = htonl(10); //Ëæ»úÖ¸¶¨Îª10£¬²¢ÇÒÔÚ±¾RTP»á»°ÖÐÈ«¾ÖΨһ 913 | 914 | if(nAvFrmLen<=nalu_sent_len) 915 | { 916 | //ÉèÖÃrtp M λ£» 917 | //printf("a"); 918 | rtp_hdr->marker=1; 919 | rtp_hdr->seq_no = htons(g_rtspClients[is].seqnum++); //ÐòÁкţ¬Ã¿·¢ËÍÒ»¸öRTP°üÔö1 920 | nalu_hdr =(NALU_HEADER*)&sendbuf[12]; 921 | nalu_hdr->F=0; 922 | nalu_hdr->NRI= nIsIFrm; 923 | nalu_hdr->TYPE= nNaluType; 924 | 925 | nalu_payload=&sendbuf[13];//ͬÀí½«sendbuf[13]¸³¸ønalu_payload 926 | memcpy(nalu_payload,buffer,nAvFrmLen); 927 | /* 928 | tmptime = g_rtspClients[is].tsvid+timestamp_increse; 929 | if(tmptime >= (-intdelta))g_rtspClients[is].tsvid=tmptime + intdelta; 930 | else g_rtspClients[is].tsvid = tmptime; 931 | */ 932 | g_rtspClients[is].tsvid = g_rtspClients[is].tsvid+timestamp_increse; 933 | 934 | rtp_hdr->timestamp=htonl(g_rtspClients[is].tsvid); 935 | bytes=nAvFrmLen+ 13 ; 936 | sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server)); 937 | } 938 | else if(nAvFrmLen>nalu_sent_len) 939 | { 940 | //printf("b"); 941 | //µÃµ½¸ÃnaluÐèÒªÓöàÉÙ³¤¶ÈΪ1400×Ö½ÚµÄRTP°üÀ´·¢ËÍ 942 | int k=0,l=0; 943 | k=nAvFrmLen/nalu_sent_len;//ÐèÒªk¸ö1400×Ö½ÚµÄRTP°ü 944 | l=nAvFrmLen%nalu_sent_len;//×îºóÒ»¸öRTP°üµÄÐèÒª×°ÔØµÄ×Ö½ÚÊý 945 | int t=0; //ÓÃÓÚָʾµ±Ç°·¢Ë͵ÄÊǵڼ¸¸ö·ÖƬRTP°ü 946 | /* 947 | tmptime = g_rtspClients[is].tsvid+timestamp_increse; 948 | if(tmptime >= (-intdelta))g_rtspClients[is].tsvid=tmptime + intdelta; 949 | else g_rtspClients[is].tsvid = tmptime; 950 | */ 951 | g_rtspClients[is].tsvid = g_rtspClients[is].tsvid+timestamp_increse; 952 | 953 | while(t<=k) 954 | { 955 | rtp_hdr->seq_no = htons(g_rtspClients[is].seqnum++); 956 | if(t==0) 957 | { 958 | //ÉèÖÃrtp M λ£» 959 | rtp_hdr->marker=0; 960 | fu_ind =(FU_INDICATOR*)&sendbuf[12]; 961 | fu_ind->F= 0; 962 | fu_ind->NRI= nIsIFrm; 963 | fu_ind->TYPE=28; 964 | 965 | //ÉèÖÃFU HEADER,²¢½«Õâ¸öHEADERÌîÈësendbuf[13] 966 | fu_hdr =(FU_HEADER*)&sendbuf[13]; 967 | fu_hdr->E=0; 968 | fu_hdr->R=0; 969 | fu_hdr->S=1; 970 | fu_hdr->TYPE=nNaluType; 971 | 972 | nalu_payload=&sendbuf[14]; 973 | memcpy(nalu_payload,buffer,nalu_sent_len); 974 | 975 | bytes=nalu_sent_len+14; 976 | sendto( udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server)); 977 | t++; 978 | 979 | } 980 | else if(k==t) 981 | { 982 | 983 | //ÉèÖÃrtp M λ£»µ±Ç°´«ÊäµÄÊÇ×îºóÒ»¸ö·ÖƬʱ¸ÃλÖÃ1 984 | rtp_hdr->marker=1; 985 | fu_ind =(FU_INDICATOR*)&sendbuf[12]; 986 | fu_ind->F= 0 ; 987 | fu_ind->NRI= nIsIFrm ; 988 | fu_ind->TYPE=28; 989 | //ÉèÖÃFU HEADER,²¢½«Õâ¸öHEADERÌîÈësendbuf[13] 990 | fu_hdr =(FU_HEADER*)&sendbuf[13]; 991 | fu_hdr->R=0; 992 | fu_hdr->S=0; 993 | fu_hdr->TYPE= nNaluType; 994 | fu_hdr->E=1; 995 | nalu_payload=&sendbuf[14]; 996 | memcpy(nalu_payload,buffer+t*nalu_sent_len,l); 997 | bytes=l+14; 998 | sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server)); 999 | t++; 1000 | } 1001 | else if(tmarker=0; 1005 | //ÉèÖÃFU INDICATOR,²¢½«Õâ¸öHEADERÌîÈësendbuf[12] 1006 | fu_ind =(FU_INDICATOR*)&sendbuf[12]; 1007 | fu_ind->F=0; 1008 | fu_ind->NRI=nIsIFrm; 1009 | fu_ind->TYPE=28; 1010 | fu_hdr =(FU_HEADER*)&sendbuf[13]; 1011 | //fu_hdr->E=0; 1012 | fu_hdr->R=0; 1013 | fu_hdr->S=0; 1014 | fu_hdr->E=0; 1015 | fu_hdr->TYPE=nNaluType; 1016 | nalu_payload=&sendbuf[14]; 1017 | memcpy(nalu_payload,buffer+t*nalu_sent_len,nalu_sent_len); 1018 | bytes=nalu_sent_len+14; 1019 | sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server)); 1020 | t++; 1021 | } 1022 | } 1023 | } 1024 | 1025 | } 1026 | 1027 | //------------------------------------------------------------ 1028 | } 1029 | /****************************************************************************** 1030 | * funciton : sent H264 stream 1031 | ******************************************************************************/ 1032 | 1033 | HI_S32 SAMPLE_COMM_VENC_Sentjin(VENC_STREAM_S *pstStream) 1034 | { 1035 | HI_S32 i,flag=0; 1036 | 1037 | for(i=0;iu32PackCount; i++) 1049 | { 1050 | HI_S32 lens=0,j,lastadd=0,newadd=0,showflap=0; 1051 | char sendbuf[320*1024]; 1052 | //char tmp[640*1024]; 1053 | lens = pstStream->pstPack[i].u32Len[0]; 1054 | memcpy(&sendbuf[0],pstStream->pstPack[i].pu8Addr[0],lens); 1055 | 1056 | if (pstStream->pstPack[i].u32Len[1] > 0) 1057 | { 1058 | memcpy(&sendbuf[lens],pstStream->pstPack[i].pu8Addr[1],lens+pstStream->pstPack[i].u32Len[1]); 1059 | lens = lens+pstStream->pstPack[i].u32Len[1]; 1060 | showflap=1; 1061 | } 1062 | /* 1063 | if(showflap) 1064 | { 1065 | printf("len:%d",lens); 1066 | for (j = 4; j < lens; j++) 1067 | { 1068 | if(j<(lens-3)) 1069 | if( sendbuf[j]==0 && sendbuf[j+1]==0 && sendbuf[j+2]==0 && sendbuf[j+3]==1) 1070 | { 1071 | newadd = j; 1072 | //memcpy(&tmp[0],&sendbuf[lastadd],newadd-lastadd); 1073 | VENC_Sent(&sendbuf[lastadd],newadd-lastadd); 1074 | printf("l:%d",newadd-lastadd); 1075 | lastadd = j; 1076 | } 1077 | } 1078 | } 1079 | if(newadd < lens) 1080 | { 1081 | VENC_Sent(&sendbuf[lastadd],lens-lastadd); 1082 | if(showflap)printf("l:%d\n",lens-lastadd); 1083 | } 1084 | */ 1085 | VENC_Sent(sendbuf,lens); 1086 | 1087 | lens = 0; 1088 | } 1089 | } 1090 | /* 1091 | if(flag) 1092 | { 1093 | //printf("a"); 1094 | for (i = 0; i < pstStream->u32PackCount; i++) 1095 | { 1096 | VENC_Sent(pstStream->pstPack[i].pu8Addr[0],pstStream->pstPack[i].u32Len[0]); 1097 | if (pstStream->pstPack[i].u32Len[1] > 0) 1098 | { 1099 | VENC_Sent(pstStream->pstPack[i].pu8Addr[1],pstStream->pstPack[i].u32Len[1]); 1100 | } 1101 | } 1102 | } 1103 | */ 1104 | /* 1105 | if(flag) 1106 | { 1107 | //printf("a"); 1108 | for (i = 0; i < pstStream->u32PackCount; i++) 1109 | { 1110 | HI_S32 lens=0; 1111 | char sendbuf[64*1024]; 1112 | char *tmp; 1113 | lens = pstStream->pstPack[i].u32Len[0]; 1114 | memcpy(&sendbuf[0],pstStream->pstPack[i].pu8Addr[0],lens); 1115 | 1116 | if (pstStream->pstPack[i].u32Len[1] > 0) 1117 | { 1118 | memcpy(&sendbuf[lens],pstStream->pstPack[i].pu8Addr[1],lens+pstStream->pstPack[i].u32Len[1]); 1119 | } 1120 | VENC_Sent(sendbuf,lens); 1121 | lens = 0; 1122 | } 1123 | } 1124 | */ 1125 | 1126 | return HI_SUCCESS; 1127 | } 1128 | /* 1129 | HI_VOID* SAMPLE_COMM_VENC_Sentjin(HI_VOID *p) 1130 | { 1131 | HI_S32 i,s32Ret,lens; 1132 | //char *tmp = (char*)malloc(sizeof(char)); 1133 | static VENC_STREAM_S *pstStream; 1134 | pstStream = (VENC_STREAM_S*)p; 1135 | 1136 | //while(1) 1137 | { 1138 | if(pstStream->u32PackCount>0)printf("spack%d\n",pstStream->u32PackCount); 1139 | for (i = 0; i < pstStream->u32PackCount; i++) 1140 | { 1141 | if(pstStream->pstPack[i].u32Len[0]>0) 1142 | VENC_Sent(pstStream->pstPack[i].pu8Addr[0],pstStream->pstPack[i].u32Len[0]); 1143 | 1144 | if (pstStream->pstPack[i].u32Len[1] > 0) 1145 | { 1146 | if(pstStream->pstPack[i].u32Len[1]>0) 1147 | VENC_Sent(pstStream->pstPack[i].pu8Addr[1],pstStream->pstPack[i].u32Len[1]); 1148 | } 1149 | } 1150 | //printf("a"); 1151 | 1152 | //step 2.5 : release stream/ 1153 | s32Ret = HI_MPI_VENC_ReleaseStream(0, pstStream); 1154 | if (HI_SUCCESS != s32Ret) 1155 | { 1156 | free(pstStream->pstPack); 1157 | pstStream->pstPack = NULL; 1158 | } 1159 | //step 2.6 : free pack nodes/ 1160 | free(pstStream->pstPack); 1161 | pstStream->pstPack = NULL; 1162 | } 1163 | return NULL; 1164 | } 1165 | */ 1166 | /****************************************************************************** 1167 | * funciton : get stream from each channels and save them 1168 | ******************************************************************************/ 1169 | HI_VOID* SAMPLE_COMM_VENC_GetVencStreamProcsent(HI_VOID *p) 1170 | { 1171 | pthread_detach(pthread_self()); 1172 | printf("RTSP:-----create send thread\n"); 1173 | //i=0,720p; i=1,VGA 640*480; i=2, 320*240; 1174 | HI_S32 i=0;//exe ch NO. 1175 | HI_S32 s32ChnTotal; 1176 | SAMPLE_VENC_GETSTREAM_PARA_S *pstPara; 1177 | HI_S32 maxfd = 0; 1178 | struct timeval TimeoutVal; 1179 | fd_set read_fds; 1180 | HI_S32 VencFd[VENC_MAX_CHN_NUM]; 1181 | VENC_CHN_STAT_S stStat; 1182 | HI_S32 s32Ret; 1183 | VENC_STREAM_S stStream; 1184 | 1185 | pstPara = (SAMPLE_VENC_GETSTREAM_PARA_S*)p; 1186 | s32ChnTotal = pstPara->s32Cnt; 1187 | 1188 | /****************************************** 1189 | step 1: check & prepare save-file & venc-fd 1190 | ******************************************/ 1191 | if (s32ChnTotal >= VENC_MAX_CHN_NUM) 1192 | { 1193 | SAMPLE_PRT("input count invaild\n"); 1194 | return NULL; 1195 | } 1196 | 1197 | //for (i = 0; i < s32ChnTotal; i++) 1198 | { 1199 | /* Set Venc Fd. */ 1200 | VencFd[i] = HI_MPI_VENC_GetFd(i); 1201 | if (VencFd[i] < 0) 1202 | { 1203 | SAMPLE_PRT("HI_MPI_VENC_GetFd failed with %#x!\n", 1204 | VencFd[i]); 1205 | return NULL; 1206 | } 1207 | if (maxfd <= VencFd[i]) 1208 | { 1209 | maxfd = VencFd[i]; 1210 | } 1211 | } 1212 | 1213 | 1214 | 1215 | udpfd = socket(AF_INET,SOCK_DGRAM,0);//UDP 1216 | printf("udp up\n"); 1217 | 1218 | /****************************************** 1219 | step 2: Start to get streams of each channel. 1220 | ******************************************/ 1221 | while (HI_TRUE == pstPara->bThreadStart) 1222 | { 1223 | HI_S32 is,flag=0; 1224 | 1225 | for(is=0;is0)printf("getpack%d\n",stStream.u32PackCount); 1305 | //printf("gt1\n"); 1306 | SAMPLE_COMM_VENC_Sentjin(&stStream); 1307 | 1308 | /* 1309 | pthread_t threadsentId = 0; 1310 | struct sched_param sentsched; 1311 | sentsched.sched_priority = 20; 1312 | //to listen visiting 1313 | pthread_create(&threadsentId, NULL, SAMPLE_COMM_VENC_Sentjin,(HI_VOID*)&stStream); 1314 | pthread_setschedparam(threadsentId,SCHED_RR,&sentsched); 1315 | */ 1316 | 1317 | //step 2.5 : release stream/ 1318 | s32Ret = HI_MPI_VENC_ReleaseStream(i, &stStream); 1319 | if (HI_SUCCESS != s32Ret) 1320 | { 1321 | free(stStream.pstPack); 1322 | stStream.pstPack = NULL; 1323 | break; 1324 | } 1325 | //step 2.6 : free pack nodes/ 1326 | free(stStream.pstPack); 1327 | stStream.pstPack = NULL; 1328 | if(exitok){ exitok++;return NULL; } 1329 | 1330 | } 1331 | } 1332 | } 1333 | } 1334 | usleep(100); 1335 | } 1336 | 1337 | return NULL; 1338 | } 1339 | /****************************************************************************** 1340 | * function : H.264@720p@30fps+H.264@VGA@30fps+H.264@QVGA@30fps 1341 | ******************************************************************************/ 1342 | HI_S32 SAMPLE_VENC_720P_CLASSIC(HI_VOID) 1343 | { 1344 | PAYLOAD_TYPE_E enPayLoad[1]= {PT_H264}; 1345 | PIC_SIZE_E enSize[1] = {PIC_HD720}; 1346 | 1347 | VB_CONF_S stVbConf; 1348 | SAMPLE_VI_CONFIG_S stViConfig; 1349 | 1350 | VPSS_GRP VpssGrp; 1351 | VPSS_CHN VpssChn; 1352 | VPSS_GRP_ATTR_S stVpssGrpAttr; 1353 | VPSS_CHN_ATTR_S stVpssChnAttr; 1354 | VPSS_CHN_MODE_S stVpssChnMode; 1355 | VPSS_EXT_CHN_ATTR_S stVpssExtChnAttr; 1356 | 1357 | VENC_GRP VencGrp; 1358 | VENC_CHN VencChn; 1359 | //SAMPLE_RC_E enRcMode= SAMPLE_RC_CBR; 1360 | //SAMPLE_RC_E enRcMode= SAMPLE_RC_FIXQP; 1361 | SAMPLE_RC_E enRcMode= SAMPLE_RC_VBR; 1362 | //HI_S32 s32ChnNum = 3; 1363 | HI_S32 s32ChnNum = 1; 1364 | 1365 | HI_S32 s32Ret = HI_SUCCESS; 1366 | HI_U32 u32BlkSize; 1367 | SIZE_S stSize; 1368 | 1369 | /****************************************** 1370 | step 1: init sys variable 1371 | ******************************************/ 1372 | memset(&stVbConf,0,sizeof(VB_CONF_S)); 1373 | 1374 | if (SONY_IMX122_DC_1080P_30FPS == SENSOR_TYPE) 1375 | { 1376 | enSize[0] = PIC_HD1080; 1377 | } 1378 | 1379 | stVbConf.u32MaxPoolCnt = 128; 1380 | 1381 | /*video buffer*/ 1382 | u32BlkSize = SAMPLE_COMM_SYS_CalcPicVbBlkSize(gs_enNorm,\ 1383 | enSize[0], SAMPLE_PIXEL_FORMAT, SAMPLE_SYS_ALIGN_WIDTH); 1384 | stVbConf.astCommPool[0].u32BlkSize = u32BlkSize; 1385 | stVbConf.astCommPool[0].u32BlkCnt = 10; 1386 | 1387 | /* hist buf*/ 1388 | stVbConf.astCommPool[3].u32BlkSize = (196*4); 1389 | stVbConf.astCommPool[3].u32BlkCnt = 6; 1390 | 1391 | /****************************************** 1392 | step 2: mpp system init. 1393 | ******************************************/ 1394 | s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf); 1395 | if (HI_SUCCESS != s32Ret) 1396 | { 1397 | SAMPLE_PRT("system init failed with %d!\n", s32Ret); 1398 | goto END_VENC_720P_CLASSIC_0; 1399 | } 1400 | 1401 | /****************************************** 1402 | step 3: start vi dev & chn to capture 1403 | ******************************************/ 1404 | stViConfig.enViMode = SENSOR_TYPE; 1405 | stViConfig.enRotate = ROTATE_NONE; 1406 | stViConfig.enNorm = VIDEO_ENCODING_MODE_AUTO; 1407 | stViConfig.enViChnSet = VI_CHN_SET_NORMAL; 1408 | s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig); 1409 | if (HI_SUCCESS != s32Ret) 1410 | { 1411 | SAMPLE_PRT("start vi failed!\n"); 1412 | goto END_VENC_720P_CLASSIC_1; 1413 | } 1414 | 1415 | /****************************************** 1416 | step 4: start vpss and vi bind vpss 1417 | ******************************************/ 1418 | s32Ret = SAMPLE_COMM_SYS_GetPicSize(gs_enNorm, enSize[0], &stSize); 1419 | if (HI_SUCCESS != s32Ret) 1420 | { 1421 | SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed!\n"); 1422 | goto END_VENC_720P_CLASSIC_1; 1423 | } 1424 | 1425 | VpssGrp = 0; 1426 | stVpssGrpAttr.u32MaxW = stSize.u32Width; 1427 | stVpssGrpAttr.u32MaxH = stSize.u32Height; 1428 | stVpssGrpAttr.bDrEn = HI_FALSE; 1429 | stVpssGrpAttr.bDbEn = HI_FALSE; 1430 | stVpssGrpAttr.bIeEn = HI_TRUE; 1431 | stVpssGrpAttr.bNrEn = HI_TRUE; 1432 | stVpssGrpAttr.bHistEn = HI_TRUE; 1433 | stVpssGrpAttr.enDieMode = VPSS_DIE_MODE_AUTO; 1434 | stVpssGrpAttr.enPixFmt = SAMPLE_PIXEL_FORMAT; 1435 | s32Ret = SAMPLE_COMM_VPSS_StartGroup(VpssGrp, &stVpssGrpAttr); 1436 | if (HI_SUCCESS != s32Ret) 1437 | { 1438 | SAMPLE_PRT("Start Vpss failed!\n"); 1439 | goto END_VENC_720P_CLASSIC_2; 1440 | } 1441 | 1442 | s32Ret = SAMPLE_COMM_VI_BindVpss(stViConfig.enViMode); 1443 | if (HI_SUCCESS != s32Ret) 1444 | { 1445 | SAMPLE_PRT("Vi bind Vpss failed!\n"); 1446 | goto END_VENC_720P_CLASSIC_3; 1447 | } 1448 | 1449 | VpssChn = 0; 1450 | memset(&stVpssChnAttr, 0, sizeof(stVpssChnAttr)); 1451 | stVpssChnAttr.bFrameEn = HI_FALSE; 1452 | stVpssChnAttr.bSpEn = HI_TRUE; 1453 | s32Ret = SAMPLE_COMM_VPSS_EnableChn(VpssGrp, VpssChn, &stVpssChnAttr, HI_NULL, HI_NULL); 1454 | if (HI_SUCCESS != s32Ret) 1455 | { 1456 | SAMPLE_PRT("Enable vpss chn failed!\n"); 1457 | goto END_VENC_720P_CLASSIC_4; 1458 | } 1459 | 1460 | /****************************************** 1461 | step 5: start stream venc 1462 | ******************************************/ 1463 | /*** HD720P **/ 1464 | VpssGrp = 0; 1465 | VpssChn = 0; 1466 | VencGrp = 0; 1467 | VencChn = 0; 1468 | s32Ret = SAMPLE_COMM_VENC_Start(VencGrp, VencChn, enPayLoad[0],\ 1469 | gs_enNorm, enSize[0], SAMPLE_RC_CBR); 1470 | if (HI_SUCCESS != s32Ret) 1471 | { 1472 | SAMPLE_PRT("Start Venc failed!\n"); 1473 | goto END_VENC_720P_CLASSIC_5; 1474 | } 1475 | 1476 | s32Ret = SAMPLE_COMM_VENC_BindVpss(VencGrp, VpssGrp, VpssChn); 1477 | if (HI_SUCCESS != s32Ret) 1478 | { 1479 | SAMPLE_PRT("Start Venc failed!\n"); 1480 | goto END_VENC_720P_CLASSIC_5; 1481 | } 1482 | 1483 | 1484 | /****************************************** 1485 | step 6: stream venc process -- get stream, then save it to file. 1486 | ******************************************/ 1487 | //s32Ret = SAMPLE_COMM_VENC_StartGetStream(s32ChnNum); 1488 | gs_stPara.bThreadStart = HI_TRUE; 1489 | gs_stPara.s32Cnt = s32ChnNum; 1490 | 1491 | struct sched_param schedvenc; 1492 | schedvenc.sched_priority = 10; 1493 | //to get stream 1494 | pthread_create(&gs_VencPid, 0, SAMPLE_COMM_VENC_GetVencStreamProcsent, (HI_VOID*)&gs_stPara); 1495 | pthread_setschedparam(gs_VencPid,SCHED_RR,&schedvenc); 1496 | 1497 | if (HI_SUCCESS != s32Ret) 1498 | { 1499 | SAMPLE_PRT("Start Venc failed!\n"); 1500 | goto END_VENC_720P_CLASSIC_5; 1501 | } 1502 | printf("please press twice ENTER to exit this sample\n"); 1503 | getchar(); 1504 | getchar(); 1505 | 1506 | /****************************************** 1507 | step 7: exit process 1508 | ******************************************/ 1509 | SAMPLE_COMM_VENC_StopGetStream(); 1510 | 1511 | END_VENC_720P_CLASSIC_5: 1512 | VpssGrp = 0; 1513 | VpssChn = 0; 1514 | VencGrp = 0; 1515 | VencChn = 0; 1516 | SAMPLE_COMM_VENC_UnBindVpss(VencGrp, VpssGrp, VpssChn); 1517 | SAMPLE_COMM_VENC_Stop(VencGrp,VencChn); 1518 | 1519 | SAMPLE_COMM_VI_UnBindVpss(stViConfig.enViMode); 1520 | END_VENC_720P_CLASSIC_4: //vpss stop 1521 | VpssGrp = 0; 1522 | VpssChn = 3; 1523 | SAMPLE_COMM_VPSS_DisableChn(VpssGrp, VpssChn); 1524 | VpssChn = 0; 1525 | SAMPLE_COMM_VPSS_DisableChn(VpssGrp, VpssChn); 1526 | VpssChn = 1; 1527 | SAMPLE_COMM_VPSS_DisableChn(VpssGrp, VpssChn); 1528 | END_VENC_720P_CLASSIC_3: //vpss stop 1529 | SAMPLE_COMM_VI_UnBindVpss(stViConfig.enViMode); 1530 | END_VENC_720P_CLASSIC_2: //vpss stop 1531 | SAMPLE_COMM_VPSS_StopGroup(VpssGrp); 1532 | END_VENC_720P_CLASSIC_1: //vi stop 1533 | SAMPLE_COMM_VI_StopVi(&stViConfig); 1534 | END_VENC_720P_CLASSIC_0: //system exit 1535 | SAMPLE_COMM_SYS_Exit(); 1536 | 1537 | return s32Ret; 1538 | } 1539 | void InitRtspServer() 1540 | { 1541 | int i; 1542 | pthread_t threadId = 0; 1543 | for(i=0;i0)exitok++; 1583 | if(exitok>10)exit(0); 1584 | } 1585 | return 1; 1586 | 1587 | 1588 | } 1589 | /***************************************************************** 1590 | Function: Èë¿Úµãº¯Êý 1591 | Description: ÓŠÓóÌÐòÈë¿Úµã 1592 | Input: argc, ²ÎÊýžöÊý 1593 | argv, ²ÎÊý×Ö·ûŽ®ÖžÕëÊý×é 1594 | Return: ²Ù×÷³É¹Š£¬Ôò·µ»Ø0£¬ÎÞÔò·µ»Ø<0 1595 | 1596 | ******************************************************************/ 1597 | int main(int argc, char* argv[]) 1598 | { 1599 | InitRtspServer(); 1600 | loop(); 1601 | } 1602 | #ifdef __cplusplus 1603 | #if __cplusplus 1604 | } 1605 | #endif 1606 | #endif /* End of #ifdef __cplusplus */---- 1607 | --------------------------------------------------------------------------------