当前位置: 首页 > article >正文

朱老师,3518e系列,第六季

第一节:概述。

首先是 将 他写好的 rtsp 源码上传,用于分析。

已经拷贝完。

第二节: h264 编码概念。

编解码 可以用cpu, 也可以用 bsp

cpu 编解码的效果不好。做控制比较好。

h264  由  VCL, NAL 组成。

NAL 关心的是 压缩的 视频 如何传输。

宏块: MB, 多个像素组成的一块, 因为一幅图片的 一篇区域 颜色是一样的。

片: slice  , 比MB 大的概念,具体是什么 ,不清楚呀。

帧: frame

I帧:  非参考帧。

P帧: 参考前面的帧,  它记录的不是 像素,而是 与前面的帧的区别。

B帧: 及参考前面的,又参考后面的。

像素--->宏块---->片----->帧---->序列--->码流。

第三节+ 第四节+第五节+ 第六节, NAL 详解。

VCL是原厂的事情, 我们只关心 NAL。

NAL 是关于网络传输的封包。

SODB: string of data bits , 这就是纯视频流, 可以播放,但是不能传输。

RBSP:  raw byte sequence payload ,

NALU : network abstraction layer units

也就是说 NAL, 只是一个头,  SODB 就是 新鲜的刚刚压缩完的数据, RBSP trailing bits 不知道是什么,  也就是说说  NALU 加上了 纯数据。

RBSP trailing bits 不知道是什么意思。

海思的 h264的 码流是由 若干个sequence 组成的。

这就是一个 sequenece

一个 sequence 的组成是。

lsps + lpps + lsei +1个I帧 + 若干p帧。

那么 你怎么 知道 ,这个就是  lsps , lpps, lsei , i 帧, p 帧呢,

就是 通过 NALU 来区分的。

也就是说, NALU 就是 lsps, lpps, lsei , i帧, p帧。

分隔符: 00 00 00 01    不是有效数据。

也就是说,  lsps , lpps , lsei  I帧 ,都要加上分隔符, 后面的p帧  就不加 分隔符了。

分隔符 后面的第一个字节 就是 NALU,  每一个位 都是由特定含义的。

也就是 lsps, lpps, lsei ,I 帧 , p帧 ,都是由 NALU的。

他们的第一个字节  就是 NAL。

这是 8个字节。

0-3 位 ,

4-8 位, 共5位, 可以表示31个数。

5: 代表 I帧

1: 代表 P帧 ,如果没有 B帧的情况下。

7 : 代表 lsps

8: 代表  lpps

6: 代表 lsei

好了, 到目前 一个字节 ,就区分出了, 这个NAUL 是什么类型了, 那么从第一个字节之后,到 00000001 ,之前的解析 都要按照 这个 帧的类型 来去分析这些数据了。

h264 sps 解析。

sps + pps 会影响播放器的行为。

sps 中有 图像的 高 , 宽的分辨率。

这是 sps 的 第一个 字节, 8位的表示。 表示的是 profiel .

level  在后面的字节中有表示。

图像的宽高 也在 后面的字节中。

h264  的 profile  + level。

profile 指的是 总体的说明

level 指的是 , 具体的 分辨率啥的。

pps , lei 中的参数就不看了。

知道什么意思就行。

CBR, VBR , 固定码率与 可变码率。 码率就是 每秒钟 编码的次数。

总结一下:

1 、 这里的帧 ,就是 对每一幅图的 压缩。

2 、 然后压缩之后的 出来的 h264 的码流 ,就是 一个一个的sequence 。

3、 一个sequence 就是有   sps , pps , sei , i帧, p帧 , 组成的。

第七节, rtsp 传输源码分析。

这里关键是 他 怎么 打包的 h264 的。

在进行压缩的时候立马 就进入 common_venc 了

这里就解释了 为什么 运行 rtsp 之后 会有一个 空文件了。

它本来是要往里面写文件的。

但是 后来 就发送出去了,不写文件了。

目前不明白这里的一包数据 ,指的是什么。

还是再 官方的 venc 的基础上改的。

主要改的文件是  sample_venc.c  + sample_common_venc.c

1 main3       RtspServer_initRtspServerListenvdRTPSendThread1     SAMPLE_VENC_720P_CLASSIC2         SAMPLE_COMM_VENC_StartGetStream3             SAMPLE_COMM_VENC_GetVencStreamProc4                 SAMPLE_COMM_VENC_SentjinVENC_Sent

总结:

1  改的内容与 ortp 的改的内容是一样的。

2  sample_venc.c 中, 多了一个 rtsp 的 init 函数。

3  samle_comm_venc. c  中 多了 , SAMPLE_COMM_VENC_Sentjin  这个发送函数,这个是自己实现的。

4 端口号的配置字段,  

5 允许链接的客户端的数量的字段。  MAX_RTSP_CLIENT  默认设置的是 1 .

它这里是用的 是 tcp 。 这里应该是  rtsp 协议。

rtsp , rtp , rtcp  与 udp , tcp

接下来分析 函数      RtspServerListen

    5 RtspServerListen4     socket3     bind2     listen1     accept16      RtspClientMsg

网络的5层模型。

rtsp 属于应用层。

这两种 消息的格式 ,对应着 , 代码中的 parse  + unparse 函数。

这种交互 ,是在 建立了 socket 之后的交互。

其实就是 client  与 server 通信的步骤。

可以看到 这里是 option , describe , setup , paly  , 而不是 什么 三次握手。

我想看看 这两部分 , 源码中 是怎么实现的。

接下来对 RtspClientMsg 进行分析。

    8     RtspClientMsg7       ParseRequestString6       OptionAnswer5       DescribeAnswer4       SetupAnswer3       PlayAnswer2       PauseAnswer1       TeardownAnswer24

descritbeanswer    里面 处理了 sdp , 这样 就不需要 在 vlc 设置 sdp 了。

SetupAnswer  函数 主要设置了  ip 端口的信息。

setup 是客户端 发起的,服务端 要进行解析,它解析出来,

setup 是 udp 的。

这里的东西比较重要。

也就是说,一个 client  , 有三个端口, 一个视频的 ,一个音频的,这两个通过 track 来区分。

还有就是, 一个rtcp 的端口,

另外这个 reqchn ,就是 通道,这个应该是 编码的通道吧?

第十一节,  rtsp 实战分析。

这里 server 在play 的时候,重新建立了 一个 udp 的连接。

他 把这个新的连接 叫做通道。

总结:

1  板子生成的 packet 是什么没搞清楚。

2 rtsp 发送的时候,看样子 就是 通过两个端口 发送的 音频+ 视频。

数据流 ,    rtp  ,  走的是  tcp

控制流, rtcp 走的是 tcp

rtsp 走的是 udp

疑问: 那么  rtcp 与 rtsp 什么关系呢?

服务器 listen 线程一直存在,  客户端 不连接之后,可以关闭 某个 客户端的线程。

   16 main15     RtspServer_init14       RtspServerListen13           socket12           bind11           listen10           accept9           RtspClientMsg8             ParseRequestString7             OptionAnswer6             DescribeAnswer5             SetupAnswer4             PlayAnswer3             PauseAnswer2             TeardownAnswer1       vdRTPSendThread18      SAMPLE_VENC_720P_CLASSIC1         SAMPLE_COMM_VENC_StartGetStream2             SAMPLE_COMM_VENC_GetVencStreamProc3                 SAMPLE_COMM_VENC_Sentjin4                     VENC_Sent

这里  vdRTPSendThread ,  也调用了 venc_send  , 不明白它 发送的是什么。

这是在发送一个 头信息。具体干什么的不知道。

    12 HI_VOID* vdRTPSendThread(HI_VOID *p)11 {10     while(1)9     {8         if(!list_empty(&RTPbuf_head))7         {65             RTPbuf_s *p = get_first_item(&RTPbuf_head,RTPbuf_s,list);4             VENC_Sent(p->buf,p->len);3             list_del(&(p->list));2             free(p->buf);1             free(p);960              p = NULL;1             count--;2             //printf("count = %d\n",count);34         }5         usleep(5000);6     }7 }

第十二节 , 直接发送与 环状发送。

为什么会有  缓冲区呢?

因为 消费 与 生产的 速度 是不一定的, 有时候 生产快,有时候消费快,如果 某一个是 固定快的话,那么就没有 缓冲区的必要了。

venc_send 就是 直接就发送了。

那么 缓冲区怎么实现的呢?

在 sample_comm_venc.c 中 。

打开 savestream

注释掉 sample_comm_venc_sendto

创建了一个队列, 并且往队列中放数据。

9 HI_S32 saveStream(VENC_STREAM_S *pstStream)8 {7     HI_S32 i,j,lens=0;65     for(j=0;j<MAX_RTSP_CLIENT;j++)//have atleast a connect4     {3         if(g_rtspClients[j].status == RTSP_SENDING)2         {1             for (i = 0; i < pstStream->u32PackCount; i++)896              {1                 RTPbuf_s *p = (RTPbuf_s *)malloc(sizeof(RTPbuf_s));2                 INIT_LIST_HEAD(&(p->list));34                 lens = pstStream->pstPack[i].u32Len-pstStream->pstPack[i].u32Offset;5                 p->buf = (char *)malloc(lens);6                 p->len = lens;7                 memcpy(p->buf,pstStream->pstPack[i].pu8Addr+pstStream->pstPack[i].u32Offset,lens);89                 list_add_tail(&(p->list),&RTPbuf_head);10                 count++;11                 //printf("count = %d\n",count);12             }13         }14     }1516     return HI_SUCCESS;17 }

然后 再 sample_venc.c 中

将 rtpsendthread 打开。

每次从队列中 拿出一个  buffer.

    20 HI_VOID* vdRTPSendThread(HI_VOID *p)19 {18     while(1)17     {16         if(!list_empty(&RTPbuf_head))15         {1413             RTPbuf_s *p = get_first_item(&RTPbuf_head,RTPbuf_s,list);12             VENC_Sent(p->buf,p->len);11             list_del(&(p->list));10             free(p->buf);9             free(p);8             p = NULL;7             count--;6             //printf("count = %d\n",count);54         }3         usleep(5000);2     }
⚑    1 }

总结: rtsp 并没有像  ortp 那样  , 去编译库文件, 而是  直接 改的 源码, 这样的话, 更容易编译。

第十三节,分包发送。

rtpstamp ,用来标记 一个 frame 的。

rtp 包头

如果是整包的话,就是 NALU .

如果分包了的话,就会 是 FU indicator  + FU header   替代的是 NALU。

就到这里吧。

----------------------------------------------------------

接下来就是 我自己的实验了。

这是重头戏。

首先总结一下, 需要改的东西。

sample_venc.c 中  

添加 所有的 函数

还需要 添加 头文件。

然后是添加 rtsp  init 函数。 这里注意将  vdRTPSendThread  函数注释掉, 因为 跟 venc_send 是 一样的。

sample_comm_venc.c 中  ,

再 最后保存的时候, 使用的是 自己的发送函数。

当然 依然是  去掉 h265的 部分。

这是我添加的代码:

首先是  sample_venc.c 文件。

#define RTSP_ENABLE 1
#if	RTSP_ENABLERTP_FIXED_HEADER        *rtp_hdr;NALU_HEADER		*nalu_hdr;
FU_INDICATOR	*fu_ind;
FU_HEADER		*fu_hdr;RTSP_CLIENT g_rtspClients[MAX_RTSP_CLIENT];int g_nSendDataChn = -1;
pthread_mutex_t g_mutex;
pthread_cond_t  g_cond;
pthread_mutex_t g_sendmutex;pthread_t g_SendDataThreadId = 0;
//HAL_CLIENT_HANDLE hMainStreamClient = NULL,hSubStreamClient = NULL,hAudioClient = NULL;
char g_rtp_playload[20];
int   g_audio_rate = 8000;
//VIDEO_NORM_E gs_enNorm = VIDEO_ENCODING_MODE_NTSC;//30fps
int g_nframerate;int exitok = 0;int udpfd;int count=0;struct list_head RTPbuf_head = LIST_HEAD_INIT(RTPbuf_head);static pthread_t gs_RtpPid;static char const* dateHeader()
{static char buf[200];
#if !defined(_WIN32_WCE)time_t tt = time(NULL);strftime(buf, sizeof buf, "Date: %a, %b %d %Y %H:%M:%S GMT\r\n", gmtime(&tt));
#endifreturn buf;
}
static char* GetLocalIP(int sock)
{struct ifreq ifreq;struct sockaddr_in *sin;char * LocalIP = malloc(20);strcpy(ifreq.ifr_name,"wlan");if (!(ioctl (sock, SIOCGIFADDR,&ifreq))){ sin = (struct sockaddr_in *)&ifreq.ifr_addr;sin->sin_family = AF_INET;strcpy(LocalIP,inet_ntoa(sin->sin_addr)); //inet_ntop(AF_INET, &sin->sin_addr,LocalIP, 16);} printf("--------------------------------------------%s\n",LocalIP);return LocalIP;
}char* strDupSize(char const* str) 
{if (str == NULL) return NULL;size_t len = strlen(str) + 1;char* copy = malloc(len);return copy;
}int ParseRequestString(char const* reqStr,unsigned reqStrSize,char* resultCmdName,unsigned resultCmdNameMaxSize,char* resultURLPreSuffix,unsigned resultURLPreSuffixMaxSize,char* resultURLSuffix,unsigned resultURLSuffixMaxSize,char* resultCSeq,unsigned resultCSeqMaxSize) 
{// This parser is currently rather dumb; it should be made smarter #####// Read everything up to the first space as the command name:int parseSucceeded = FALSE;unsigned i;for (i = 0; i < resultCmdNameMaxSize-1 && i < reqStrSize; ++i) {char c = reqStr[i];if (c == ' ' || c == '\t') {parseSucceeded = TRUE;break;}resultCmdName[i] = c;}resultCmdName[i] = '\0';if (!parseSucceeded) return FALSE;// Skip over the prefix of any "rtsp://" or "rtsp:/" URL that follows:unsigned j = i+1;while (j < reqStrSize && (reqStr[j] == ' ' || reqStr[j] == '\t')) ++j; // skip over any additional white spacefor (j = i+1; j < reqStrSize-8; ++j) {if ((reqStr[j] == 'r' || reqStr[j] == 'R')&& (reqStr[j+1] == 't' || reqStr[j+1] == 'T')&& (reqStr[j+2] == 's' || reqStr[j+2] == 'S')&& (reqStr[j+3] == 'p' || reqStr[j+3] == 'P')&& reqStr[j+4] == ':' && reqStr[j+5] == '/') {j += 6;if (reqStr[j] == '/') {// This is a "rtsp://" URL; skip over the host:port part that follows:++j;while (j < reqStrSize && reqStr[j] != '/' && reqStr[j] != ' ') ++j;} else {// This is a "rtsp:/" URL; back up to the "/":--j;}i = j;break;}}// Look for the URL suffix (before the following "RTSP/"):parseSucceeded = FALSE;unsigned k;for (k = i+1; k < reqStrSize-5; ++k) {if (reqStr[k] == 'R' && reqStr[k+1] == 'T' &&reqStr[k+2] == 'S' && reqStr[k+3] == 'P' && reqStr[k+4] == '/') {while (--k >= i && reqStr[k] == ' ') {} // go back over all spaces before "RTSP/"unsigned k1 = k;while (k1 > i && reqStr[k1] != '/' && reqStr[k1] != ' ') --k1;// the URL suffix comes from [k1+1,k]// Copy "resultURLSuffix":if (k - k1 + 1 > resultURLSuffixMaxSize) return FALSE; // there's no roomunsigned n = 0, k2 = k1+1;while (k2 <= k) resultURLSuffix[n++] = reqStr[k2++];resultURLSuffix[n] = '\0';// Also look for the URL 'pre-suffix' before this:unsigned k3 = --k1;while (k3 > i && reqStr[k3] != '/' && reqStr[k3] != ' ') --k3;// the URL pre-suffix comes from [k3+1,k1]// Copy "resultURLPreSuffix":if (k1 - k3 + 1 > resultURLPreSuffixMaxSize) return FALSE; // there's no roomn = 0; k2 = k3+1;while (k2 <= k1) resultURLPreSuffix[n++] = reqStr[k2++];resultURLPreSuffix[n] = '\0';i = k + 7; // to go past " RTSP/"parseSucceeded = TRUE;break;}}if (!parseSucceeded) return FALSE;// Look for "CSeq:", skip whitespace,// then read everything up to the next \r or \n as 'CSeq':parseSucceeded = FALSE;for (j = i; j < reqStrSize-5; ++j) {if (reqStr[j] == 'C' && reqStr[j+1] == 'S' && reqStr[j+2] == 'e' &&reqStr[j+3] == 'q' && reqStr[j+4] == ':') {j += 5;unsigned n;while (j < reqStrSize && (reqStr[j] ==  ' ' || reqStr[j] == '\t')) ++j;for (n = 0; n < resultCSeqMaxSize-1 && j < reqStrSize; ++n,++j) {char c = reqStr[j];if (c == '\r' || c == '\n') {parseSucceeded = TRUE;break;}resultCSeq[n] = c;}resultCSeq[n] = '\0';break;}}if (!parseSucceeded) return FALSE;return TRUE;
}int OptionAnswer(char *cseq, int sock)
{if (sock != 0){char buf[1024];memset(buf,0,1024);char *pTemp = buf;pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sPublic: %s\r\n\r\n",cseq,dateHeader(),"OPTIONS,DESCRIBE,SETUP,PLAY,PAUSE,TEARDOWN");int reg = send(sock, buf,strlen(buf),0);if(reg <= 0){return FALSE;}else{printf(">>>>>%s\n",buf);}return TRUE;}return FALSE;
}int DescribeAnswer(char *cseq,int sock,char * urlSuffix,char* recvbuf)
{if (sock != 0){char sdpMsg[1024];char buf[2048];memset(buf,0,2048);memset(sdpMsg,0,1024);char*localip;localip = GetLocalIP(sock);char *pTemp = buf;pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n",cseq);pTemp += sprintf(pTemp,"%s",dateHeader());pTemp += sprintf(pTemp,"Content-Type: application/sdp\r\n");char *pTemp2 = sdpMsg;pTemp2 += sprintf(pTemp2,"v=0\r\n");pTemp2 += sprintf(pTemp2,"o=StreamingServer 3331435948 1116907222000 IN IP4 %s\r\n",localip);pTemp2 += sprintf(pTemp2,"s=H.264\r\n");pTemp2 += sprintf(pTemp2,"c=IN IP4 0.0.0.0\r\n");pTemp2 += sprintf(pTemp2,"t=0 0\r\n");pTemp2 += sprintf(pTemp2,"a=control:*\r\n");/*H264 TrackID=0 RTP_PT 96*/pTemp2 += sprintf(pTemp2,"m=video 0 RTP/AVP 96\r\n");pTemp2 += sprintf(pTemp2,"a=control:trackID=0\r\n");pTemp2 += sprintf(pTemp2,"a=rtpmap:96 H264/90000\r\n");pTemp2 += sprintf(pTemp2,"a=fmtp:96 packetization-mode=1; sprop-parameter-sets=%s\r\n", "AAABBCCC");
#if 1/*G726*/pTemp2 += sprintf(pTemp2,"m=audio 0 RTP/AVP 97\r\n");pTemp2 += sprintf(pTemp2,"a=control:trackID=1\r\n");if(strcmp(g_rtp_playload,"AAC")==0){pTemp2 += sprintf(pTemp2,"a=rtpmap:97 MPEG4-GENERIC/%d/2\r\n",16000);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");}else{pTemp2 += sprintf(pTemp2,"a=rtpmap:97 G726-32/%d/1\r\n",8000);pTemp2 += sprintf(pTemp2,"a=fmtp:97 packetization-mode=1\r\n");}	
#endifpTemp += sprintf(pTemp,"Content-length: %d\r\n", strlen(sdpMsg));     pTemp += sprintf(pTemp,"Content-Base: rtsp://%s/%s/\r\n\r\n",localip,urlSuffix);//printf("mem ready\n");strcat(pTemp, sdpMsg);free(localip);//printf("Describe ready sent\n");int re = send(sock, buf, strlen(buf),0);if(re <= 0){return FALSE;}else{printf(">>>>>%s\n",buf);}}return TRUE;
}
void ParseTransportHeader(char const* buf,StreamingMode* streamingMode,char**streamingModeString,char**destinationAddressStr,u_int8_t* destinationTTL,portNumBits* clientRTPPortNum, // if UDPportNumBits* clientRTCPPortNum, // if UDPunsigned char* rtpChannelId, // if TCPunsigned char* rtcpChannelId // if TCP){// Initialize the result parameters to default values:*streamingMode = RTP_UDP;*streamingModeString = NULL;*destinationAddressStr = NULL;*destinationTTL = 255;*clientRTPPortNum = 0;*clientRTCPPortNum = 1; *rtpChannelId = *rtcpChannelId = 0xFF;portNumBits p1, p2;unsigned ttl, rtpCid, rtcpCid;// First, find "Transport:"while (1) {if (*buf == '\0') return; // not foundif (strncasecmp(buf, "Transport: ", 11) == 0) break;++buf;}// Then, run through each of the fields, looking for ones we handle:char const* fields = buf + 11;char* field = strDupSize(fields);while (sscanf(fields, "%[^;]", field) == 1) {if (strcmp(field, "RTP/AVP/TCP") == 0) {*streamingMode = RTP_TCP;} else if (strcmp(field, "RAW/RAW/UDP") == 0 ||strcmp(field, "MP2T/H2221/UDP") == 0) {*streamingMode = RAW_UDP;//*streamingModeString = strDup(field);} else if (strncasecmp(field, "destination=", 12) == 0){//delete[] destinationAddressStr;free(destinationAddressStr);//destinationAddressStr = strDup(field+12);} else if (sscanf(field, "ttl%u", &ttl) == 1) {destinationTTL = (u_int8_t)ttl;} else if (sscanf(field, "client_port=%hu-%hu", &p1, &p2) == 2) {*clientRTPPortNum = p1;*clientRTCPPortNum = p2;} else if (sscanf(field, "client_port=%hu", &p1) == 1) {*clientRTPPortNum = p1;*clientRTCPPortNum = streamingMode == RAW_UDP ? 0 : p1 + 1;} else if (sscanf(field, "interleaved=%u-%u", &rtpCid, &rtcpCid) == 2) {*rtpChannelId = (unsigned char)rtpCid;*rtcpChannelId = (unsigned char)rtcpCid;}fields += strlen(field);while (*fields == ';') ++fields; // skip over separating ';' charsif (*fields == '\0' || *fields == '\r' || *fields == '\n') break;}free(field);
}int SetupAnswer(char *cseq,int sock,int SessionId,char * urlSuffix,char* recvbuf,int* rtpport, int* rtcpport)
{if (sock != 0){char buf[1024];memset(buf,0,1024);StreamingMode streamingMode;char* streamingModeString; // set when RAW_UDP streaming is specifiedchar* clientsDestinationAddressStr;u_int8_t clientsDestinationTTL;portNumBits clientRTPPortNum, clientRTCPPortNum;unsigned char rtpChannelId, rtcpChannelId;ParseTransportHeader(recvbuf,&streamingMode, &streamingModeString,&clientsDestinationAddressStr, &clientsDestinationTTL,&clientRTPPortNum, &clientRTCPPortNum,&rtpChannelId, &rtcpChannelId);//Port clientRTPPort(clientRTPPortNum);//Port clientRTCPPort(clientRTCPPortNum);*rtpport = clientRTPPortNum;*rtcpport = clientRTCPPortNum;char *pTemp = buf;char*localip;localip = GetLocalIP(sock);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",cseq,dateHeader(),localip,ntohs(htons(clientRTPPortNum)), ntohs(htons(clientRTCPPortNum)), ntohs(2000),ntohs(2001),SessionId);free(localip);int reg = send(sock, buf,strlen(buf),0);if(reg <= 0){return FALSE;}else{printf(">>>>>%s",buf);}return TRUE;}return FALSE;
}int PlayAnswer(char *cseq, int sock,int SessionId,char* urlPre,char* recvbuf)
{if (sock != 0){char buf[1024];memset(buf,0,1024);char *pTemp = buf;char*localip;localip = GetLocalIP(sock);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",cseq,dateHeader(),SessionId,localip,urlPre);free(localip);int reg = send(sock, buf,strlen(buf),0);if(reg <= 0){return FALSE;}else{printf(">>>>>%s",buf);udpfd = socket(AF_INET,SOCK_DGRAM,0);//UDPstruct sockaddr_in server;server.sin_family=AF_INET;server.sin_port=htons(g_rtspClients[0].rtpport[0]);          server.sin_addr.s_addr=inet_addr(g_rtspClients[0].IP);connect(udpfd,(struct sockaddr *)&server,sizeof(server));printf("udp up\n");}return TRUE;}return FALSE;
}int PauseAnswer(char *cseq,int sock,char *recvbuf)
{if (sock != 0){char buf[1024];memset(buf,0,1024);char *pTemp = buf;pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%s\r\n\r\n",cseq,dateHeader());int reg = send(sock, buf,strlen(buf),0);if(reg <= 0){return FALSE;}else{printf(">>>>>%s",buf);}return TRUE;}return FALSE;
}int TeardownAnswer(char *cseq,int sock,int SessionId,char *recvbuf)
{if (sock != 0){char buf[1024];memset(buf,0,1024);char *pTemp = buf;pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sSession: %d\r\n\r\n",cseq,dateHeader(),SessionId);int reg = send(sock, buf,strlen(buf),0);if(reg <= 0){return FALSE;}else{printf(">>>>>%s",buf);close(udpfd);}return TRUE;}return FALSE;
}
void * RtspClientMsg(void*pParam)
{pthread_detach(pthread_self());int nRes;char pRecvBuf[RTSP_RECV_SIZE];RTSP_CLIENT * pClient = (RTSP_CLIENT*)pParam;memset(pRecvBuf,0,sizeof(pRecvBuf));printf("RTSP:-----Create Client %s\n",pClient->IP);while(pClient->status != RTSP_IDLE){nRes = recv(pClient->socket, pRecvBuf, RTSP_RECV_SIZE,0);//printf("-------------------%d\n",nRes);if(nRes < 1){//usleep(1000);printf("RTSP:Recv Error--- %d\n",nRes);g_rtspClients[pClient->index].status = RTSP_IDLE;g_rtspClients[pClient->index].seqnum = 0;g_rtspClients[pClient->index].tsvid = 0;g_rtspClients[pClient->index].tsaud = 0;close(pClient->socket);break;}char cmdName[PARAM_STRING_MAX];char urlPreSuffix[PARAM_STRING_MAX];char urlSuffix[PARAM_STRING_MAX];char cseq[PARAM_STRING_MAX];ParseRequestString(pRecvBuf,nRes,cmdName,sizeof(cmdName),urlPreSuffix,sizeof(urlPreSuffix),urlSuffix,sizeof(urlSuffix),cseq,sizeof(cseq));char *p = pRecvBuf;printf("<<<<<%s\n",p);//printf("\--------------------------\n");//printf("%s %s\n",urlPreSuffix,urlSuffix);if(strstr(cmdName, "OPTIONS")){OptionAnswer(cseq,pClient->socket);}else if(strstr(cmdName, "DESCRIBE")){DescribeAnswer(cseq,pClient->socket,urlSuffix,p);//printf("-----------------------------DescribeAnswer %s %s\n",//	urlPreSuffix,urlSuffix);}else if(strstr(cmdName, "SETUP")){int rtpport,rtcpport;int trackID=0;SetupAnswer(cseq,pClient->socket,pClient->sessionid,urlPreSuffix,p,&rtpport,&rtcpport);sscanf(urlSuffix, "trackID=%u", &trackID);//printf("----------------------------------------------TrackId %d\n",trackID);if(trackID<0 || trackID>=2)trackID=0;g_rtspClients[pClient->index].rtpport[trackID] = rtpport;g_rtspClients[pClient->index].rtcpport= rtcpport;g_rtspClients[pClient->index].reqchn = atoi(urlPreSuffix);if(strlen(urlPreSuffix)<100)strcpy(g_rtspClients[pClient->index].urlPre,urlPreSuffix);//printf("-----------------------------SetupAnswer %s-%d-%d\n",//	urlPreSuffix,g_rtspClients[pClient->index].reqchn,rtpport);}else if(strstr(cmdName, "PLAY")){PlayAnswer(cseq,pClient->socket,pClient->sessionid,g_rtspClients[pClient->index].urlPre,p);g_rtspClients[pClient->index].status = RTSP_SENDING;printf("Start Play\n",pClient->index);//printf("-----------------------------PlayAnswer %d %d\n",pClient->index);//usleep(100);}else if(strstr(cmdName, "PAUSE")){PauseAnswer(cseq,pClient->socket,p);}else if(strstr(cmdName, "TEARDOWN")){TeardownAnswer(cseq,pClient->socket,pClient->sessionid,p);g_rtspClients[pClient->index].status = RTSP_IDLE;g_rtspClients[pClient->index].seqnum = 0;g_rtspClients[pClient->index].tsvid = 0;g_rtspClients[pClient->index].tsaud = 0;close(pClient->socket);}//if(exitok){ exitok++;return NULL; } }printf("RTSP:-----Exit Client %s\n",pClient->IP);return NULL;
}void * RtspServerListen(void*pParam)
{int s32Socket;struct sockaddr_in servaddr;int s32CSocket;int s32Rtn;int s32Socket_opt_value = 1;int nAddrLen;struct sockaddr_in addrAccept;int bResult;memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(RTSP_SERVER_PORT); s32Socket = socket(AF_INET, SOCK_STREAM, 0);if (setsockopt(s32Socket ,SOL_SOCKET,SO_REUSEADDR,&s32Socket_opt_value,sizeof(int)) == -1)     {return (void *)(-1);}s32Rtn = bind(s32Socket, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in));if(s32Rtn < 0){return (void *)(-2);}s32Rtn = listen(s32Socket, 50);   if(s32Rtn < 0){return (void *)(-2);}nAddrLen = sizeof(struct sockaddr_in);int nSessionId = 1000;while ((s32CSocket = accept(s32Socket, (struct sockaddr*)&addrAccept, &nAddrLen)) >= 0){printf("<<<<RTSP Client %s Connected...\n", inet_ntoa(addrAccept.sin_addr));int nMaxBuf = 10 * 1024; // 脧碌脥鲁艙芦禄谩路脰脜盲 2 x nMaxBuf 碌脛禄潞鲁氓沤贸脨隆if(setsockopt(s32CSocket, SOL_SOCKET, SO_SNDBUF, (char*)&nMaxBuf, sizeof(nMaxBuf)) == -1)printf("RTSP:!!!!!! Enalarge socket sending buffer error !!!!!!\n");int i;int bAdd=FALSE;for(i=0;i<MAX_RTSP_CLIENT;i++){if(g_rtspClients[i].status == RTSP_IDLE){memset(&g_rtspClients[i],0,sizeof(RTSP_CLIENT));g_rtspClients[i].index = i;g_rtspClients[i].socket = s32CSocket;g_rtspClients[i].status = RTSP_CONNECTED ;//RTSP_SENDING;g_rtspClients[i].sessionid = nSessionId++;strcpy(g_rtspClients[i].IP,inet_ntoa(addrAccept.sin_addr));pthread_t threadIdlsn = 0;struct sched_param sched;sched.sched_priority = 1;//to return ACKechopthread_create(&threadIdlsn, NULL, RtspClientMsg, &g_rtspClients[i]);//pthread_setschedparam(threadIdlsn,SCHED_RR,&sched);bAdd = TRUE;break;}}if(bAdd==FALSE){memset(&g_rtspClients[0],0,sizeof(RTSP_CLIENT));g_rtspClients[0].index = 0;g_rtspClients[0].socket = s32CSocket;g_rtspClients[0].status = RTSP_CONNECTED ;//RTSP_SENDING;g_rtspClients[0].sessionid = nSessionId++;strcpy(g_rtspClients[0].IP,inet_ntoa(addrAccept.sin_addr));pthread_t threadIdlsn = 0;struct sched_param sched;sched.sched_priority = 1;//to return ACKechopthread_create(&threadIdlsn, NULL, RtspClientMsg, &g_rtspClients[0]);//pthread_setschedparam(threadIdlsn,SCHED_RR,&sched);bAdd = TRUE;}//if(exitok){ exitok++;return NULL; } 	}if(s32CSocket < 0){// HI_OUT_Printf(0, "RTSP listening on port %d,accept err, %d\n", RTSP_SERVER_PORT, s32CSocket);}printf("----- INIT_RTSP_Listen() Exit !! \n");return NULL;
}
HI_S32 VENC_Sent(char *buffer,int buflen)
{HI_S32 i;int is=0;int nChanNum=0;for(is=0;is<MAX_RTSP_CLIENT;is++){if(g_rtspClients[is].status!=RTSP_SENDING){continue;}int heart = g_rtspClients[is].seqnum % 10000;char* nalu_payload;int nAvFrmLen = 0;int nIsIFrm = 0;int nNaluType = 0;char sendbuf[500*1024+32];nAvFrmLen = buflen;struct sockaddr_in server;server.sin_family=AF_INET;server.sin_port=htons(g_rtspClients[is].rtpport[0]);          server.sin_addr.s_addr=inet_addr(g_rtspClients[is].IP);int	bytes=0;unsigned int timestamp_increse=0;timestamp_increse=(unsigned int)(90000.0 / 25);rtp_hdr =(RTP_FIXED_HEADER*)&sendbuf[0]; rtp_hdr->payload     = RTP_H264;   rtp_hdr->version     = 2;          rtp_hdr->marker    = 0;           rtp_hdr->ssrc      = htonl(10);   if(nAvFrmLen<=nalu_sent_len){rtp_hdr->marker=1;rtp_hdr->seq_no     = htons(g_rtspClients[is].seqnum++); nalu_hdr =(NALU_HEADER*)&sendbuf[12]; nalu_hdr->F=0; nalu_hdr->NRI=  nIsIFrm; nalu_hdr->TYPE=  nNaluType;nalu_payload=&sendbuf[13];memcpy(nalu_payload,buffer,nAvFrmLen);g_rtspClients[is].tsvid = g_rtspClients[is].tsvid+timestamp_increse;            rtp_hdr->timestamp=htonl(g_rtspClients[is].tsvid);bytes=nAvFrmLen+ 13 ;				sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server));}else if(nAvFrmLen>nalu_sent_len){int k=0,l=0;k=nAvFrmLen/nalu_sent_len;l=nAvFrmLen%nalu_sent_len;int t=0;        g_rtspClients[is].tsvid = g_rtspClients[is].tsvid+timestamp_increse;rtp_hdr->timestamp=htonl(g_rtspClients[is].tsvid);            while(t<=k){rtp_hdr->seq_no = htons(g_rtspClients[is].seqnum++);if(t==0){rtp_hdr->marker=0;fu_ind =(FU_INDICATOR*)&sendbuf[12];fu_ind->F= 0; fu_ind->NRI= nIsIFrm;fu_ind->TYPE=28;fu_hdr =(FU_HEADER*)&sendbuf[13];fu_hdr->E=0;fu_hdr->R=0;fu_hdr->S=1;fu_hdr->TYPE=nNaluType;nalu_payload=&sendbuf[14];memcpy(nalu_payload,buffer,nalu_sent_len);bytes=nalu_sent_len+14;					sendto( udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server));t++;}else if(k==t){rtp_hdr->marker=1;fu_ind =(FU_INDICATOR*)&sendbuf[12]; fu_ind->F= 0 ;fu_ind->NRI= nIsIFrm ;fu_ind->TYPE=28;fu_hdr =(FU_HEADER*)&sendbuf[13];fu_hdr->R=0;fu_hdr->S=0;fu_hdr->TYPE= nNaluType;fu_hdr->E=1;nalu_payload=&sendbuf[14];memcpy(nalu_payload,buffer+t*nalu_sent_len,l);bytes=l+14;		sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server));t++;}else if(t<k && t!=0){rtp_hdr->marker=0;fu_ind =(FU_INDICATOR*)&sendbuf[12]; fu_ind->F=0; fu_ind->NRI=nIsIFrm;fu_ind->TYPE=28;fu_hdr =(FU_HEADER*)&sendbuf[13];//fu_hdr->E=0;fu_hdr->R=0;fu_hdr->S=0;fu_hdr->E=0;fu_hdr->TYPE=nNaluType;nalu_payload=&sendbuf[14];memcpy(nalu_payload,buffer+t*nalu_sent_len,nalu_sent_len);bytes=nalu_sent_len+14;	sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server));t++;}}}}//------------------------------------------------------------
}
/******************************************************************************
* funciton : sent H264 stream
******************************************************************************/HI_S32 SAMPLE_COMM_VENC_Sentjin(VENC_STREAM_S *pstStream)
{HI_S32 i,flag=0;for(i=0;i<MAX_RTSP_CLIENT;i++)//have atleast a connect{if(g_rtspClients[i].status == RTSP_SENDING){flag = 1;break;}}if(flag){for (i = 0; i < pstStream->u32PackCount; i++){HI_S32 lens=0,j,lastadd=0,newadd=0,showflap=0;char sendbuf[320*1024];//char tmp[640*1024];lens = pstStream->pstPack[i].u32Len-pstStream->pstPack[i].u32Offset;memcpy(&sendbuf[0],pstStream->pstPack[i].pu8Addr+pstStream->pstPack[i].u32Offset,lens);//printf("lens = %d, count= %d\n",lens,count++);VENC_Sent(sendbuf,lens);		lens = 0;}}return HI_SUCCESS;
}HI_S32 saveStream(VENC_STREAM_S *pstStream)
{HI_S32 i,j,lens=0;for(j=0;j<MAX_RTSP_CLIENT;j++)//have atleast a connect{if(g_rtspClients[j].status == RTSP_SENDING){for (i = 0; i < pstStream->u32PackCount; i++){RTPbuf_s *p = (RTPbuf_s *)malloc(sizeof(RTPbuf_s));INIT_LIST_HEAD(&(p->list));lens = pstStream->pstPack[i].u32Len-pstStream->pstPack[i].u32Offset;p->buf = (char *)malloc(lens);p->len = lens;memcpy(p->buf,pstStream->pstPack[i].pu8Addr+pstStream->pstPack[i].u32Offset,lens);list_add_tail(&(p->list),&RTPbuf_head);count++;//printf("count = %d\n",count);}}}return HI_SUCCESS;
}void RtspServer_init(void)
{int i;pthread_t threadId = 0;memset(&g_rtp_playload,0,sizeof(g_rtp_playload));strcpy(&g_rtp_playload,"G726-32");g_audio_rate = 8000;pthread_mutex_init(&g_sendmutex,NULL);pthread_mutex_init(&g_mutex,NULL);pthread_cond_init(&g_cond,NULL);memset(&g_rtspClients,0,sizeof(RTSP_CLIENT)*MAX_RTSP_CLIENT);//pthread_create(&g_SendDataThreadId, NULL, SendDataThread, NULL);struct sched_param thdsched;thdsched.sched_priority = 2;//to listen visitingpthread_create(&threadId, NULL, RtspServerListen, NULL);//pthread_setschedparam(threadId,SCHED_RR,&thdsched);printf("RTSP:-----Init Rtsp server\n");pthread_create(&gs_RtpPid, 0, vdRTPSendThread, NULL);//exitok++;}
void RtspServer_exit(void)
{return;
}HI_VOID* vdRTPSendThread(HI_VOID *p)
{while(1){if(!list_empty(&RTPbuf_head)){RTPbuf_s *p = get_first_item(&RTPbuf_head,RTPbuf_s,list);VENC_Sent(p->buf,p->len);list_del(&(p->list));free(p->buf);free(p);p = NULL;count--;//printf("count = %d\n",count);}usleep(5000);}
}#endif

main 函数里这么添加。

    11 #if RTSP_ENABLE10     RtspServer_init();9 #endif87     ret = sample_venc_choose_mode(index);6     if (ret == TD_SUCCESS) {5         printf("program exit normally!\n");4     } else {3         printf("program exit abnormally!\n");2     }1

添加需要的库。

  171 #define RTSP_ENABLE 1234 #if RTSP_ENABLE56 #include <unistd.h>7 #include <stdio.h>8 #include <string.h>9 #include <stdlib.h>10 #include <time.h>11 #include <netdb.h>12 #include <sys/socket.h>1314 #include <sys/ioctl.h>15 #include <fcntl.h>16 #include <pthread.h>17 #include <sys/ipc.h>18 #include <sys/msg.h>19 #include <netinet/if_ether.h>20 #include <net/if.h>2122 #include <linux/if_ether.h>23 #include <linux/sockios.h>24 #include <netinet/in.h>25 #include <arpa/inet.h>2627 #endif28

然后是 sample_comm_venc.c  文件。

在最开头  添加。

    14 #define RTSP_ENABLE 1
  2865 static td_void sample_comm_fd_isset(sample_comm_venc_stream_proc_info *stream_proc_info, fd_set *read_fds,1     ot_venc_stream_buf_info *stream_buf_info, ot_payload_type *payload_type, sample_venc_getstream_para *para)2 {3     td_s32 i, ret;45 //    for (i = 0; (i < stream_proc_info->chn_total) && (i < OT_VENC_MAX_CHN_NUM); i++) {6     //7 //topeet wang added8     for (i = 1; (i < stream_proc_info->chn_total) && (i < OT_VENC_MAX_CHN_NUM); i++) {9         if (FD_ISSET(stream_proc_info->venc_fd[i], read_fds)) {10             stream_proc_info->venc_chn = para->venc_chn[i];11             ret = sample_comm_get_stream_from_one_channl(stream_proc_info, i, stream_buf_info, payload_type);12             if (ret == SAMPLE_RETURN_CONTINUE) {13                 continue;14             } else if (ret == SAMPLE_RETURN_BREAK) {15                 break;16             }17         }18     }19 }

然后是  sample_comm_save_frame_to_file  函数。

     3 #ifndef __LITEOS__4     ot_unused(stream_buf_info);5678 #if RTSP_ENABLE9     SAMPLE_COMM_VENC_Sentjin(&stStream);10 #else11     ret = sample_comm_venc_save_stream(stream_proc_info->file[index], stream);12 #endif13

接下来编译一遍看看。

出现报错

.1.0/smp/a7_linux/source/mpp/sample/venc/../common/sample_comm_venc.c
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc/../common/sample_comm_venc.c: In function 'sample_comm_save_frame_to_file':
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc/../common/sample_comm_venc.c:2777:5: warning: implicit declaration of function 'SAMPLE_COMM_VENC_Sentjin' [-Wimplicit-function-declaration]2777 |     SAMPLE_COMM_VENC_Sentjin(&stStream);|     ^~~~~~~~~~~~~~~~~~~~~~~~
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc/../common/sample_comm_venc.c:2777:31: error: 'stStream' undeclared (first use in this function); did you mean 'stream'?2777 |     SAMPLE_COMM_VENC_Sentjin(&stStream);|                               ^~~~~~~~|                               stream
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc/../common/sample_comm_venc.c:2777:31: note: each undeclared identifier is reported only once for each function it appears in
make: *** [<builtin>: /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc/../common/sample_comm_venc.o] Error 1
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc#

将函数   SAMPLE_COMM_VENC_Sentjin(&stStream)   改为  SAMPLE_COMM_VENC_Sentjin(&stream)

依然有报错。

/include -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/out/include/exp_inc -DVER_X=1 -DVER_Y=0 -DVER_Z=0 -DVER_P=0 -DVER_B=10 -DUSER_BIT_32 -DKERNEL_BIT_32 -DOT
_RELEASE -Wno-date-time -DSENSOR0_TYPE=SC4336P_MIPI_4M_30FPS_10BIT -DSENSOR1_TYPE=SC4336P_MIPI_4M_30FPS_10BIT -DBOARD_TYPE=DMEB_QFN -DOT_ACODEC_TYPE_INNER -DOT_VQE_USE_STATIC_MODULE_REGI
STER -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc/../common -I/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/
venc/../audio/adp   -c -o sample_venc.o sample_venc.c
sample_venc.c:79:1: error: unknown type name 'RTP_FIXED_HEADER'79 | RTP_FIXED_HEADER        *rtp_hdr;| ^~~~~~~~~~~~~~~~
sample_venc.c:81:1: error: unknown type name 'NALU_HEADER'81 | NALU_HEADER  *nalu_hdr;| ^~~~~~~~~~~
sample_venc.c:82:1: error: unknown type name 'FU_INDICATOR'82 | FU_INDICATOR *fu_ind;| ^~~~~~~~~~~~
sample_venc.c:83:1: error: unknown type name 'FU_HEADER'83 | FU_HEADER  *fu_hdr;| ^~~~~~~~~
sample_venc.c:86:1: error: unknown type name 'RTSP_CLIENT'86 | RTSP_CLIENT g_rtspClients[MAX_RTSP_CLIENT];| ^~~~~~~~~~~
sample_venc.c:86:27: error: 'MAX_RTSP_CLIENT' undeclared here (not in a function)86 | RTSP_CLIENT g_rtspClients[MAX_RTSP_CLIENT];|                           ^~~~~~~~~~~~~~~
sample_venc.c:107:8: error: variable 'RTPbuf_head' has initializer but incomplete type107 | struct list_head RTPbuf_head = LIST_HEAD_INIT(RTPbuf_head);|        ^~~~~~~~~
sample_venc.c:107:32: warning: implicit declaration of function 'LIST_HEAD_INIT' [-Wimplicit-function-declaration]107 | struct list_head RTPbuf_head = LIST_HEAD_INIT(RTPbuf_head);|                                ^~~~~~~~~~~~~~
sample_venc.c:107:47: error: 'RTPbuf_head' has an incomplete type 'struct list_head'

解决: 

原来  在 sample_comm.h 中 还有 需要改动的内容。

添加这些内容。


#if	RTSP_ENABLE#include "list.h"
#if !defined(WIN32)#define __PACKED__        __attribute__ ((__packed__))
#else#define __PACKED__ 
#endiftypedef enum
{RTSP_VIDEO=0,RTSP_VIDEOSUB=1,RTSP_AUDIO=2,RTSP_YUV422=3,RTSP_RGB=4,RTSP_VIDEOPS=5,RTSP_VIDEOSUBPS=6
}enRTSP_MonBlockType;struct _RTP_FIXED_HEADER
{/**//* 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 payload:7;        /**//* RTP_PAYLOAD_RTSP */unsigned char marker:1;        /**//* expect 1 *//**//* bytes 2, 3 */unsigned short seq_no;            /**//* bytes 4-7 */unsigned  long timestamp;        /**//* bytes 8-11 */unsigned long ssrc;            /**//* stream number is used here. */
} __PACKED__;typedef struct _RTP_FIXED_HEADER RTP_FIXED_HEADER;struct _NALU_HEADER
{//byte 0unsigned char TYPE:5;unsigned char NRI:2;unsigned char F:1;    }__PACKED__; /**//* 1 BYTES */typedef struct _NALU_HEADER NALU_HEADER;struct _FU_INDICATOR
{//byte 0unsigned char TYPE:5;unsigned char NRI:2; unsigned char F:1;    }__PACKED__; /**//* 1 BYTES */typedef struct _FU_INDICATOR FU_INDICATOR;struct _FU_HEADER
{//byte 0unsigned char TYPE:5;unsigned char R:1;unsigned char E:1;unsigned char S:1;    
} __PACKED__; /**//* 1 BYTES */
typedef struct _FU_HEADER FU_HEADER;struct _AU_HEADER
{//byte 0, 1unsigned short au_len;//byte 2,3unsigned  short frm_len:13;  unsigned char au_index:3;
} __PACKED__; /**//* 1 BYTES */
typedef struct _AU_HEADER AU_HEADER;extern void RtspServer_init(void);
extern void RtspServer_exit(void);int AddFrameToRtspBuf(int nChanNum,enRTSP_MonBlockType eType, char * pData, unsigned int  nSize, unsigned int  nVidFrmNum,int bIFrm);extern HI_S32 SAMPLE_COMM_VENC_Sentjin(VENC_STREAM_S *pstStream);
extern HI_S32 saveStream(VENC_STREAM_S *pstStream);
extern HI_VOID* vdRTPSendThread(HI_VOID *p);#define nalu_sent_len        1400
//#define nalu_sent_len        1400
#define RTP_H264                    96
#define RTP_AUDIO              97
#define MAX_RTSP_CLIENT       1
#define RTSP_SERVER_PORT      554
#define RTSP_RECV_SIZE        1024
#define RTSP_MAX_VID          (640*1024)
#define RTSP_MAX_AUD          (15*1024)#define AU_HEADER_SIZE    4
#define PARAM_STRING_MAX        100typedef unsigned short u_int16_t;
typedef unsigned char u_int8_t;
typedef u_int16_t portNumBits;
typedef u_int32_t netAddressBits;
typedef long long _int64;
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE  1
#endif
#define AUDIO_RATE    8000
#define PACKET_BUFFER_END            (unsigned int)0x00000000typedef struct 
{int startblock;//浠h〃寮€濮嬫枃浠跺潡鍙?int endblock;//浠h〃缁撴潫鏂囦欢鍧楀彿int BlockFileNum;//浠h〃褰曞儚娈垫暟}IDXFILEHEAD_INFO;//.IDX鏂囦欢鐨勫ご淇℃伅typedef struct 
{_int64 starttime;//浠h〃寮€濮媠hijian_int64 endtime;//浠h〃缁撴潫shijian int startblock;//浠h〃寮€濮嬫枃浠跺潡鍙?int endblock;//浠h〃缁撴潫鏂囦欢鍧楀彿int stampnum;//浠h〃鏃堕棿鎴虫暟閲?
}IDXFILEBLOCK_INFO;//.IDX鏂囦欢娈典俊鎭?typedef struct 
{int blockindex;//浠h〃鎵€鍦ㄦ枃浠跺潡鍙?int pos;//浠h〃璇ユ椂闂存埑鍦ㄦ枃浠跺潡鐨勪綅缃?_int64 time;//浠h〃鏃堕棿鎴虫椂闂存埑鐨勬椂闂寸偣
}IDXSTAMP_INFO;//.IDX鏂囦欢鐨勬椂闂存埑淇℃伅typedef struct 
{char filename[150];//浠h〃鎵€鍦ㄦ枃浠跺潡鍙?int pos;//浠h〃璇ユ椂闂存埑鍦ㄦ枃浠跺潡鐨勪綅缃?_int64 time;//浠h〃鏃堕棿鎴虫椂闂存埑鐨勬椂闂寸偣
}FILESTAMP_INFO;//.IDX鏂囦欢鐨勬椂闂存埑淇℃伅typedef struct 
{char channelid[9];_int64 starttime;//浠h〃寮€濮媠hijian_int64 endtime;//浠h〃缁撴潫shijian _int64 session;int		type;	//绫诲瀷int		encodetype;//缂栫爜鏍煎紡;
}FIND_INFO;//.IDX鏂囦欢鐨勬椂闂存埑淇℃伅typedef enum
{RTP_UDP,RTP_TCP,RAW_UDP
}StreamingMode;RTP_FIXED_HEADER  *rtp_hdr;
NALU_HEADER		  *nalu_hdr;
FU_INDICATOR	  *fu_ind;
FU_HEADER		  *fu_hdr;
AU_HEADER            *au_hdr;extern char g_rtp_playload[20];//脛卢脠脧G726-32
extern int   g_audio_rate;//脛卢脠脧8000typedef enum
{RTSP_IDLE = 0,RTSP_CONNECTED = 1,RTSP_SENDING = 2,
}RTSP_STATUS;typedef struct
{int  nVidLen;int  nAudLen;int bIsIFrm;int bWaitIFrm;int bIsFree;char vidBuf[RTSP_MAX_VID];char audBuf[RTSP_MAX_AUD];
}RTSP_PACK;typedef struct
{int index;int socket;int reqchn;int seqnum;int seqnum2;unsigned int tsvid;unsigned int tsaud;int status;int sessionid;int rtpport[2];int rtcpport;char IP[20];char urlPre[PARAM_STRING_MAX];
}RTSP_CLIENT;typedef struct
{int  vidLen;int  audLen;int  nFrameID;char vidBuf[RTSP_MAX_VID];char audBuf[RTSP_MAX_AUD];
}FRAME_PACK;
typedef struct
{int startcodeprefix_len;      //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested)unsigned len;                 //! Length of the NAL unit (Excluding the start code, which does not belong to the NALU)unsigned max_size;            //! Nal Unit Buffer sizeint forbidden_bit;            //! should be always FALSEint nal_reference_idc;        //! NALU_PRIORITY_xxxxint nal_unit_type;            //! NALU_TYPE_xxxxchar *buf;                    //! contains the first byte followed by the EBSPunsigned short lost_packets;  //! true, if packet loss is detected
} NALU_t;
extern int udpfd;
extern RTSP_CLIENT g_rtspClients[MAX_RTSP_CLIENT];
typedef struct _rtpbuf
{struct list_head list;HI_S32 len;char * buf;
}RTPbuf_s;
extern struct list_head RTPbuf_head;#endif

依然后报错。

rt_demo region scene_auto security_subsys smart_ae svc_venc svp uvc_app venc vgs vie cccccccc
make[1]: Entering directory '/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common'
~~~~~~~~~~Start build audio~~~~~~~~~~
make[1]: Entering directory '/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/audio'
/opt/linux/x86-arm/arm-v01c02-linux-musleabi-gcc/bin/../lib/gcc/arm-linux-musleabi/10.3.0/../../../../arm-linux-musleabi/bin/ld: /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/audio/../common/sample_comm_venc.o: in function `sample_comm_venc_get_venc_stream_proc':
sample_comm_venc.c:(.text.sample_comm_venc_get_venc_stream_proc+0x59a): undefined reference to `SAMPLE_COMM_VENC_Sentjin'
collect2: error: ld returned 1 exit status
make[1]: *** [/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/audio/../smp_linux.mak:14: sample_audio] Error 1
make[1]: Leaving directory '/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/audio'
make: *** [Makefile:31: audio] Error 2
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample#
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample#

解决:  我需要重新编译一下  sample_comm_venc.c

但是依然有报错。

(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common# make clean
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common# make
In file included from /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm_sys.c:5:
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm.h:143:8: error: unknown type name 'HI_S32'143 | extern HI_S32 SAMPLE_COMM_VENC_Sentjin(VENC_STREAM_S *pstStream);|        ^~~~~~
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm.h:143:40: error: unknown type name 'VENC_STREAM_S'143 | extern HI_S32 SAMPLE_COMM_VENC_Sentjin(VENC_STREAM_S *pstStream);|                                        ^~~~~~~~~~~~~
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm.h:144:8: error: unknown type name 'HI_S32'144 | extern HI_S32 saveStream(VENC_STREAM_S *pstStream);|        ^~~~~~
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm.h:144:26: error: unknown type name 'VENC_STREAM_S'144 | extern HI_S32 saveStream(VENC_STREAM_S *pstStream);|                          ^~~~~~~~~~~~~
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm.h:145:8: error: unknown type name 'HI_VOID'145 | extern HI_VOID* vdRTPSendThread(HI_VOID *p);|        ^~~~~~~
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm.h:145:33: error: unknown type name 'HI_VOID'145 | extern HI_VOID* vdRTPSendThread(HI_VOID *p);|                                 ^~~~~~~
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm.h:167:9: error: unknown type name 'u_int32_t'167 | typedef u_int32_t netAddressBits;|         ^~~~~~~~~
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm.h:297:2: error: unknown type name 'HI_S32'297 |  HI_S32 len;|  ^~~~~~
make: *** [Makefile:14: /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm_sys.o] Error 1

这个报错 就是 改类型。

我是这么改的。

改的是 sample_comm.h

    12 #define HI_VOID         void11 typedef int HI_S32;10 typedef unsigned int  u_int32_t;9

     5 //extern HI_S32 SAMPLE_COMM_VENC_Sentjin(VENC_STREAM_S *pstStream);6 //extern HI_S32 saveStream(VENC_STREAM_S *pstStream);7 //8 extern HI_S32 SAMPLE_COMM_VENC_Sentjin(ot_venc_stream *pstStream);9 extern HI_S32 saveStream(ot_venc_stream *pstStream);1011 extern HI_VOID* vdRTPSendThread(HI_VOID *p);

编译通过。

(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common# make clean
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common# make
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm_venc.c: In function 'sample_comm_save_frame_to_file':
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm_venc.c:2777:30: warning: passing argument 1 of 'SAMPLE_COMM_VENC_Sentjin' from incompatible pointer type [-Wincompatible-pointer-types]2777 |     SAMPLE_COMM_VENC_Sentjin(&stream);|                              ^~~~~~~|                              ||                              ot_venc_stream **
In file included from /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm_venc.c:23:
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm.h:147:56: note: expected 'ot_venc_stream *' but argument is of type 'ot_venc_stream **'147 | extern HI_S32 SAMPLE_COMM_VENC_Sentjin(ot_venc_stream *pstStream);|                                        ~~~~~~~~~~~~~~~~^~~~~~~~~
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm_venc.c: In function 'sample_comm_venc_get_venc_stream_proc':
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm_venc.c:2787:8: warning: 'ret' may be used uninitialized in this function [-Wmaybe-uninitialized]2787 |     if (ret != TD_SUCCESS) {|        ^
/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common/../common/sample_comm_venc.c:2744:12: note: 'ret' was declared here2744 |     td_s32 ret, fd;|            ^~~
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common#
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common#
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common#
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common#
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/common#

然后去编译  sample_venc.c 文件。

依然是有报错。

sample_venc.c:773:12: warning: unused variable 'i' [-Wunused-variable]773 |     HI_S32 i;|            ^
sample_venc.c: At top level:
sample_venc.c:910:33: error: unknown type name 'VENC_STREAM_S'910 | HI_S32 SAMPLE_COMM_VENC_Sentjin(VENC_STREAM_S *pstStream)|                                 ^~~~~~~~~~~~~
sample_venc.c:941:19: error: unknown type name 'VENC_STREAM_S'941 | HI_S32 saveStream(VENC_STREAM_S *pstStream)|                   ^~~~~~~~~~~~~
sample_venc.c: In function 'RtspServer_init':
sample_venc.c:976:9: warning: passing argument 1 of 'strcpy' from incompatible pointer type [-Wincompatible-pointer-types]976 |  strcpy(&g_rtp_playload,"G726-32");|         ^~~~~~~~~~~~~~~|         ||         char (*)[20]
In file included from sample_venc.c:7:
/opt/linux/x86-arm/arm-v01c02-linux-musleabi-gcc/target/usr/include/string.h:33:15: note: expected 'char * restrict' but argument is of type 'char (*)[20]'33 | char *strcpy (char *__restrict, const char *__restrict);|               ^
sample_venc.c:985:21: warning: variable 'thdsched' set but not used [-Wunused-but-set-variable]985 |  struct sched_param thdsched;

解决: 在这个文件中 依然去改 这个函数。

改的 是 sample_venc.c

    36 /******************************************************************************35 * funciton : sent H264 stream34 ******************************************************************************/3332 HI_S32 SAMPLE_COMM_VENC_Sentjin(ot_venc_stream *pstStream)31 {30     HI_S32 i,flag=0;2928     for(i=0;i<MAX_RTSP_CLIENT;i++)//have atleast a connect27     {26         if(g_rtspClients[i].status == RTSP_SENDING)25         {24             flag = 1;23             break;22         }21     }20     if(flag)19     {18         for (i = 0; i < pstStream->u32PackCount; i++)17         {16         HI_S32 lens=0,j,lastadd=0,newadd=0,showflap=0;15         char sendbuf[320*1024];14         //char tmp[640*1024];13         lens = pstStream->pstPack[i].u32Len-pstStream->pstPack[i].u32Offset;12         memcpy(&sendbuf[0],pstStream->pstPack[i].pu8Addr+pstStream->pstPack[i].u32Offset,lens);11         //printf("lens = %d, count= %d\n",lens,count++);10         VENC_Sent(sendbuf,lens);9         lens = 0;8         }765     }4     return HI_SUCCESS;3 }21 HI_S32 saveStream(ot_venc_stream *pstStream)942  {1     HI_S32 i,j,lens=0;23     for(j=0;j<MAX_RTSP_CLIENT;j++)//have atleast a connect4     {5         if(g_rtspClients[j].status == RTSP_SENDING)6         {7             for (i = 0; i < pstStream->u32PackCount; i++)8             {

重新编译之后 依然是 有错误。

sample_venc.c:773:12: warning: unused variable 'i' [-Wunused-variable]773 |     HI_S32 i;|            ^
sample_venc.c: In function 'SAMPLE_COMM_VENC_Sentjin':
sample_venc.c:924:31: error: 'ot_venc_stream' has no member named 'u32PackCount'924 |      for (i = 0; i < pstStream->u32PackCount; i++)|                               ^~
sample_venc.c:929:21: error: 'ot_venc_stream' has no member named 'pstPack'; did you mean 'pack'?929 |   lens = pstStream->pstPack[i].u32Len-pstStream->pstPack[i].u32Offset;|                     ^~~~~~~|                     pack
sample_venc.c:929:50: error: 'ot_venc_stream' has no member named 'pstPack'; did you mean 'pack'?929 |   lens = pstStream->pstPack[i].u32Len-pstStream->pstPack[i].u32Offset;|                                                  ^~~~~~~|                                                  pack
sample_venc.c:930:33: error: 'ot_venc_stream' has no member named 'pstPack'; did you mean 'pack'?930 |   memcpy(&sendbuf[0],pstStream->pstPack[i].pu8Addr+pstStream->pstPack[i].u32Offset,lens);|                                 ^~~~~~~|                                 pack
sample_venc.c:930:63: error: 'ot_venc_stream' has no member named 'pstPack'; did you mean 'pack'?930 |   memcpy(&sendbuf[0],pstStream->pstPack[i].pu8Addr+pstStream->pstPack[i].u32Offset,lens);|                                                               ^~~~~~~|                                                               pack
sample_venc.c:926:38: warning: unused variable 'showflap' [-Wunused-variable]926 |   HI_S32 lens=0,j,lastadd=0,newadd=0,showflap=0;|                                      ^~~~~~~~
sample_venc.c:926:29: warning: unused variable 'newadd' [-Wunused-variable]926 |   HI_S32 lens=0,j,lastadd=0,newadd=0,showflap=0;|                             ^~~~~~
sample_venc.c:926:19: warning: unused variable 'lastadd' [-Wunused-variable]926 |   HI_S32 lens=0,j,lastadd=0,newadd=0,showflap=0;|                   ^~~~~~~
sample_venc.c:926:17: warning: unused variable 'j' [-Wunused-variable]926 |   HI_S32 lens=0,j,lastadd=0,newadd=0,showflap=0;|                 ^
sample_venc.c:938:12: error: 'HI_SUCCESS' undeclared (first use in this function); did you mean 'TD_SUCCESS'?938 |     return HI_SUCCESS;|            ^~~~~~~~~~

这个错误 也好改,依然是 结构体的问题。

解决:

解释照着 ortp 去改。

改动文件, sample_venc.c

改动如下:

       4 /******************************************************************************3 * funciton : sent H264 stream2 ******************************************************************************/1910  HI_S32 SAMPLE_COMM_VENC_Sentjin(ot_venc_stream *pstStream)1 {2     HI_S32 i,flag=0;34     for(i=0;i<MAX_RTSP_CLIENT;i++)//have atleast a connect5     {6         if(g_rtspClients[i].status == RTSP_SENDING)7         {8             flag = 1;9             break;10         }11     }12     if(flag)13     {14        // for (i = 0; i < pstStream->u32PackCount; i++)15         for (i = 0; i < pstStream->pack_cnt; i++)16         {17         HI_S32 lens=0,j,lastadd=0,newadd=0,showflap=0;18         char sendbuf[320*1024];19         //char tmp[640*1024];20     //  lens = pstStream->pstPack[i].u32Len-pstStream->pstPack[i].u32Offset;21     //  memcpy(&sendbuf[0],pstStream->pstPack[i].pu8Addr+pstStream->pstPack[i].u32Offset,lens);22         lens = pstStream->pack[i].len-pstStream->pack[i].offset;23         memcpy(&sendbuf[0],pstStream->pack[i].addr+pstStream->pack[i].offset,lens);24         //printf("lens = %d, count= %d\n",lens,count++);25         VENC_Sent(sendbuf,lens);26         lens = 0;27         }282930     }31     return TD_SUCCESS;32 }4 HI_S32 saveStream(ot_venc_stream *pstStream)5 {6     HI_S32 i,j,lens=0;78     for(j=0;j<MAX_RTSP_CLIENT;j++)//have atleast a connect9     {10         if(g_rtspClients[j].status == RTSP_SENDING)11         {12           //  for (i = 0; i < pstStream->u32PackCount; i++)13             for (i = 0; i < pstStream->pack_cnt; i++)14             {15                 RTPbuf_s *p = (RTPbuf_s *)malloc(sizeof(RTPbuf_s));16                 INIT_LIST_HEAD(&(p->list));1718                 lens = pstStream->pack[i].len-pstStream->pack[i].offset;19                 p->buf = (char *)malloc(lens);20                 p->len = lens;21                 memcpy(p->buf,pstStream->pack[i].addr+pstStream->pack[i].offset,lens);2223                 list_add_tail(&(p->list),&RTPbuf_head);24                 count++;25                 //printf("count = %d\n",count);26             }27         }28     }2930     return TD_SUCCESS;31 }32

重新编译 但是依然是报错。

sample_venc.c:140:18: warning: 'gs_RtpPid' defined but not used [-Wunused-variable]140 | static pthread_t gs_RtpPid;|                  ^~~~~~~~~
/opt/linux/x86-arm/arm-v01c02-linux-musleabi-gcc/bin/../lib/gcc/arm-linux-musleabi/10.3.0/../../../../arm-linux-musleabi/bin/ld: /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_
linux/source/mpp/sample/venc/../common/sample_comm_isp.o:(.bss.au_hdr+0x0): multiple definition of `au_hdr'; /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sam
ple/venc/../common/sample_comm_sys.o:(.bss.au_hdr+0x0): first defined here
/opt/linux/x86-arm/arm-v01c02-linux-musleabi-gcc/bin/../lib/gcc/arm-linux-musleabi/10.3.0/../../../../arm-linux-musleabi/bin/ld: /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_
linux/source/mpp/sample/venc/../common/sample_comm_isp.o:(.bss.fu_hdr+0x0): multiple definition of `fu_hdr'; /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sam
ple/venc/../common/sample_comm_sys.o:(.bss.fu_hdr+0x0): first defined here
/opt/linux/x86-arm/arm-v01c02-linux-musleabi-gcc/bin/../lib/gcc/arm-linux-musleabi/10.3.0/../../../../arm-linux-musleabi/bin/ld: /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_
linux/source/mpp/sample/venc/../common/sample_comm_isp.o:(.bss.fu_ind+0x0): multiple definition of `fu_ind'; /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sam
ple/venc/../common/sample_comm_sys.o:(.bss.fu_ind+0x0): first defined here
/opt/linux/x86-arm/arm-v01c02-linux-musleabi-gcc/bin/../lib/gcc/arm-linux-musleabi/10.3.0/../../../../arm-linux-musleabi/bin/ld: /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_
linux/source/mpp/sample/venc/../common/sample_comm_isp.o:(.bss.nalu_hdr+0x0): multiple definition of `nalu_hdr'; /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp
/sample/venc/../common/sample_comm_sys.o:(.bss.nalu_hdr+0x0): first defined here
/opt/linux/x86-arm/arm-v01c02-linux-musleabi-gcc/bin/../lib/gcc/arm-linux-musleabi/10.3.0/../../../../arm-linux-musleabi/bin/ld: /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_
linux/source/mpp/sample/venc/../common/sample_comm_isp.o:(.bss.rtp_hdr+0x0): multiple definition of `rtp_hdr'; /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/s
ample/venc/../common/sample_comm_sys.o:(.bss.rtp_hdr+0x0): first defined here
/opt/linux/x86-arm/arm-v01c02-linux-musleabi-gcc/bin/../lib/gcc/arm-linux-musleabi/10.3.0/../../../../arm-linux-musleabi/bin/ld: /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_
linux/source/mpp/sample/venc/../common/sample_comm_vi.o:(.bss.au_hdr+0x0): multiple definition of `au_hdr'; /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/samp
le/venc/../common/sample_comm_sys.o:(.bss.au_hdr+0x0): first defined here
/opt/linux/x86-arm/arm-v01c02-linux-musleabi-gcc/bin/../lib/gcc/arm-linux-musleabi/10.3.0/../../../../arm-linux-musleabi/bin/ld: /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_
linux/source/mpp/sample/venc/../common/sample_comm_vi.o:(.bss.fu_hdr+0x0): multiple definition of `fu_hdr'; /home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/samp
le/venc/../common/sample_comm_sys.o:(.bss.fu_hdr+0x0): first defined here
/opt/linux/x86-arm/arm-v01c02-linux-musleabi-gcc/bin/../lib/gcc/arm-linux-musleabi/10.3.0/../../../../arm-linux-musl

解决:

最终在 sample_comm.h 中   注释掉定义。

    18 typedef enum17 {16     RTP_UDP,15     RTP_TCP,14     RAW_UDP13 }StreamingMode;121110 // RTP_FIXED_HEADER  *rtp_hdr;9 // NALU_HEADER        *nalu_hdr;8 // FU_INDICATOR   *fu_ind;7 // FU_HEADER          *fu_hdr;6 // AU_HEADER            *au_hdr;543 extern char g_rtp_playload[20];//脛卢脠脧G726-322 extern int   g_audio_rate;//脛卢脠脧80001244  typedef enum1 {2     RTSP_IDLE = 0,3     RTSP_CONNECTED = 1,4     RTSP_SENDING = 2,

然后在  sample_venc.c 中 ,加上 static .

    1110 #if RTSP_ENABLE98 static RTP_FIXED_HEADER        *rtp_hdr;7 static NALU_HEADER      *nalu_hdr;6 static  FU_INDICATOR    *fu_ind;5 static  FU_HEADER       *fu_hdr;432 RTSP_CLIENT g_rtspClients[MAX_RTSP_CLIENT];1118  int g_nSendDataChn = -1;
E    1 pthread_mutex_t g_mutex;     ■ Unknown type name 'pthread_mutex_t'
E    2 pthread_cond_t  g_cond;     ■ Unknown type name 'pthread_cond_t'; did you mean 'thread_contrl'? (fix available)
E    3 pthread_mutex_t g_sendmutex; 

最终编译通过。

      |         ||         char (*)[20]
In file included from sample_venc.c:7:
/opt/linux/x86-arm/arm-v01c02-linux-musleabi-gcc/target/usr/include/string.h:33:15: note: expected 'char * restrict' but argument is of type 'char (*)[20]'33 | char *strcpy (char *__restrict, const char *__restrict);|               ^
sample_venc.c:988:21: warning: variable 'thdsched' set but not used [-Wunused-but-set-variable]988 |  struct sched_param thdsched;|                     ^~~~~~~~
sample_venc.c:975:6: warning: unused variable 'i' [-Wunused-variable]975 |  int i;|      ^
sample_venc.c: In function 'VENC_Sent':
sample_venc.c:904:1: warning: control reaches end of non-void function [-Wreturn-type]904 | }| ^
At top level:
sample_venc.c:139:18: warning: 'gs_RtpPid' defined but not used [-Wunused-variable]139 | static pthread_t gs_RtpPid;|                  ^~~~~~~~~
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc#
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc#
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc#
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc#
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc#
(myenv) root@topeet:/home/topeet/source_code/Hi3516CV610_SDK_V1.0.1.0/smp/a7_linux/source/mpp/sample/venc#

接下来 放到 板子上 测试一下 , 程序能不能运行。

先不管 vlc .

居然没有报错。

~ # ./sample_venc 0
RTSP:-----Init Rtsp server
wrap online is 1, buf line is 128, buf size is 458544[MPP] Version: [HI3516CV610_MPP_V1.0.1.0 B040 Release], Build Time[Sep  7 2024, 17:51:12]linear mode
===================================================================================
vi_pipe:0,== SC4336P_MIPI_27Minput_2lane_10bit_630Mbps_2560x1440_30fps Init OK! ==
===================================================================================
ISP Dev 0 running !
please input choose gop mode!0) normal p.1) dual p.2) smart p.
random: crng init done
0
please input choose rc mode!c) cbr.v) vbr.b) abr.a) avbr.x) cvbr.q) qvbr.f) fix_qp
c
please press twice ENTER to exit this sampleprogram exit normally!
~ #

继续测试,当我 打开 vlc 时 出现这个报错。

linear mode
===================================================================================
vi_pipe:0,== SC4336P_MIPI_27Minput_2lane_10bit_630Mbps_2560x1440_30fps Init OK! ==
===================================================================================
ISP Dev 0 running !
please input choose gop mode!0) normal p.1) dual p.2) smart p.
random: crng init done
0
please input choose rc mode!c) cbr.v) vbr.b) abr.a) avbr.x) cvbr.q) qvbr.f) fix_qp
c
please press twice ENTER to exit this sample
<<<<RTSP Client 192.168.1.114 Connected...
RTSP:-----Create Client 192.168.1.114
<<<<<SETUP rtsp://192.168.1.121:554/stream_chn.h264 RTSP/1.0
CSeq: 0
Transport: RTP/AVP;unicast;client_port=9284-9285--------------------------------------------
>>>>>RTSP/1.0 200 OK
CSeq: 0
Date: Thu, Jan 01 1970 00:01:10 GMT
Transport: RTP/AVP;unicast;destination=;client_port=9284-9285;server_port=53255-53511
Session: 1000<<<<<PLAY rtsp://192.168.1.121:554/stream=0 RTSP/1.0
CSeq: 1
Session: 1000: RTP/AVP;unicast;client_port=9284-9285--------------------------------------------
>>>>>RTSP/1.0 200 OK
CSeq: 1
Date: Thu, Jan 01 1970 00:01:10 GMT
Range: npt=0.000-
Session: 1000
RTP-Info: url=rtsp:///;seq=0udp up
Start Play
Segmentation fault
~ #

感觉跟我之前的重复定义 是 有关的。

这个报错解决不了了。

但是我发现一个 重要的错误。

注意:

他可以这样写。

但是我必须这样写。

因为我这里 本身已经是指针了。

报错终于改好了。

改的是 ,去掉头文件的重复的定义,

并且 在 sample_venc.c 中的函数中。

改了这些 结构体。

出现过 , pstStream 的地方 ,都要做相应的改动。

最终测试 结果可以了。


>>>>>RTSP/1.0 200 OK
CSeq: 3
Date: Thu, Jan 01 1970 00:03:30 GMT
Content-Type: application/sdp
Content-length: 357
Content-Base: rtsp://client_port=62728-62/stream_chn0.h264/v=0
o=StreamingServer 3331435948 1116907222000 IN IP4 client_port=62728-62
s=H.264
c=IN IP4 0.0.0.0
t=0 0
a=control:*
m=video 0 RTP/AVP 96
a=control:trackID=0
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; sprop-parameter-sets=AAABBCCC
m=audio 0 RTP/AVP 97
a=control:trackID=1
a=rtpmap:97 G726-32/8000/1
a=fmtp:97 packetization-mode=1<<<<<SETUP rtsp://client_port=62728-62/stream_chn0.h264/trackID=0 RTSP/1.0
CSeq: 4
User-Agent: LibVLC/2.2.6 (LIVE555 Streaming Media v2016.02.22)
Transport: RTP/AVP;unicast;client_port=53120-53121--------------------------------------------client_port=62728-62
>>>>>RTSP/1.0 200 OK
CSeq: 4
Date: Thu, Jan 01 1970 00:03:30 GMT
Transport: RTP/AVP;unicast;destination=client_port=62728-62;client_port=53120-53121;server_port=53255-53511
Session: 1002<<<<<SETUP rtsp://client_port=62728-62/stream_chn0.h264/trackID=1 RTSP/1.0
CSeq: 5
User-Agent: LibVLC/2.2.6 (LIVE555 Streaming Media v2016.02.22)
Transport: RTP/AVP;unicast;client_port=53122-53123
Session: 1002--------------------------------------------client_port=53120-53
>>>>>RTSP/1.0 200 OK
CSeq: 5
Date: Thu, Jan 01 1970 00:03:30 GMT
Transport: RTP/AVP;unicast;destination=client_port=53120-53;client_port=53122-53123;server_port=53255-53511
Session: 1002<<<<<PLAY rtsp://client_port=62728-62/stream_chn0.h264/ RTSP/1.0
CSeq: 6
User-Agent: LibVLC/2.2.6 (LIVE555 Streaming Media v2016.02.22)
Session: 1002
Range: npt=0.000-;client_port=53122-53123
Session: 1002--------------------------------------------client_port=62728-62
>>>>>RTSP/1.0 200 OK
CSeq: 6
Date: Thu, Jan 01 1970 00:03:30 GMT
Range: npt=0.000-
Session: 1002
RTP-Info: url=rtsp://client_port=62728-62/stream_chn0.h264;seq=0udp up
Start Play
<<<<<TEARDOWN rtsp://client_port=62728-62/stream_chn0.h264/ RTSP/1.0
CSeq: 7
User-Agent: LibVLC/2.2.6 (LIVE555 Streaming Media v2016.02.22)
Session: 1002npt=0.000-;client_port=53122-53123
Session: 1002>>>>>RTSP/1.0 200 OK
CSeq: 7
Date: Thu, Jan 01 1970 00:03:50 GMT
Session: 1002RTSP:-----Exit Client 192.168.1.114
^C^Cprogram exit normally!
~ # ^C

将 ortp 可以的代码 +  rtsp 可以的代码 打包  保存到网盘中

http://www.lryc.cn/news/2379714.html

相关文章:

  • ElasticSearch-集群
  • 一文掌握工业相机选型计算
  • 记录心态和工作变化
  • 深入理解 TypeScript 中的 unknown 类型:安全处理未知数据的最佳实践
  • LabVIEW机械振动信号分析与故障诊断
  • Helm配置之为特定Deployment配置特定Docker仓库(覆盖全局配置)
  • 【Spring】Spring中的适配器模式
  • GO学习指南
  • 2、ubuntu系统配置OpenSSH | 使用vscode或pycharm远程连接
  • MySQL面试知识点详解
  • 小白入门:GitHub 远程仓库使用全攻略
  • RPC与SOAP的区别
  • Day11-苍穹外卖(数据统计篇)
  • Tomcat简述介绍
  • 《从零开始:Spring Cloud Eureka 配置与服务注册全流程》​
  • 如何保证RabbitMQ消息的顺序性?
  • FPGA学习知识(汇总)
  • c语言 写一个五子棋
  • Redisson分布式锁-锁的可重入、可重试、WatchDog超时续约、multLock联锁(一文全讲透,超详细!!!)
  • Python爬虫实战:研究源码还原技术,实现逆向解密
  • WordPress Relevanssi插件时间型SQL注入漏洞(CVE-2025-4396)
  • Adobe Illustrator学习备忘
  • C#中的dynamic与var:看似相似却迥然不同
  • 求职困境:开发、AI、运维、自动化
  • 语言模型:AM-Thinking-v1 能和大参数语言模型媲美的 32B 单卡推理模型
  • ChatGPT:OpenAI Codex—一款基于云的软件工程 AI 代理,赋能 ChatGPT,革新软件开发模式
  • docker compose up -d 是一个用于 通过 Docker Compose 在后台启动多容器应用 的命令
  • 智能视觉检测技术:制造业质量管控的“隐形守护者”
  • 利用html制作简历网页和求职信息网页
  • Problem E: List练习