EasyRTSPClient 基于live555构建而成. 今天讲讲EasyRTSPClient的设计过程服务器
EasyRTSPClient,主要包括如下部分:
1. 建立live555对象, 链接相机和收流
2. 解析收到的视频分辨率
3. 将SDP、音视频流、分辨率及其它相关信息经过回调函数进行回调
4. 回调链接、断线状态
5. 根据参数执行是否重连markdown
网上不少介绍的都是使用testRTSPClient来作客户端, 这个是没有问题的,但有一点须要注意的是demo中的代码,都是阻塞式的,以下:session
env->taskScheduler().doEventLoop(&eventLoopWatchVariable);
这样就在主线程中阻塞了, 若是我须要它退出,该怎样实现呢?
有两种方法,目的是相同的,实现方式略有不一样罢了:
1. 外部改变eventLoopWatchVariable的值为1
2. 经过BasicTaskScheduler0::doEventLoop(char* watchVariable)的实现能够看出, 这里其实是进行一个无限循环. 当 watchVariable的值不为0时就退出. 因此咱们能够本身建立一个线程,在线程内部实现调用 pTaskScheduler0->SingleStep(0), 便可实现对该线程的自由控制; 至关于1个线程对应1路到摄像机的取流;ide
解析分辨率主要是sps_pps.h .c实现,是从VLC中提取出来的相关代码, 可正常解析H264,H265的分辨率;函数
在Live555的continueAfterDESCRIBE的回调函数中, 解析出SDP信息进行回调
void continueAfterDESCRIBE(RTSPClient* rtspClient, int resultCode, char* resultString) 工具
if (NULL != sdpDescription) { if (NULL != pClient) pClient->SetSDP(sdpDescription, (int)strlen(sdpDescription)); char *sprop_parameter_sets = strstr(sdpDescription, "sprop-parameter-sets="); if (NULL != sprop_parameter_sets) { AnalysisH264SPSPPS(pClient, sprop_parameter_sets+21); } else { sprop_parameter_sets = strstr(sdpDescription, "sprop-sps="); if (NULL != sprop_parameter_sets) { AnalysisH265SPSPPS(pClient, sprop_parameter_sets); } } //回调出媒体信息 MediaSubsessionIterator iter(*scs.session); MediaSubsession* subsession; while ((subsession = iter.next()) != NULL) { if (strcmp(subsession->mediumName(), "video") == 0) { if (strcmp(subsession->codecName(), "H264") == 0) { mediainfo.videoCodec = VIDEO_CODEC_H264; } else if (strcmp(subsession->codecName(), "H265") == 0) { mediainfo.videoCodec = VIDEO_CODEC_H265; } else if (strcmp(subsession->codecName(), "MP4V-ES") == 0) { mediainfo.videoCodec = VIDEO_CODEC_MPEG4; } else if (strcmp(subsession->codecName(), "JPEG") == 0) { mediainfo.videoCodec = VIDEO_CODEC_MJPEG; } mediainfo.videoFps = (float)subsession->videoFPS(); mediainfo.videoWidth = pClient->params.width; mediainfo.videoHeight = pClient->params.height; } if (strcmp(subsession->mediumName(), "audio") == 0) { } } if (NULL != clientObj && NULL !=clientObj->callback) { RTSPClientCallBack pRtspCallback = (RTSPClientCallBack )clientObj->callback; if (NULL != pRtspCallback) { pRtspCallback(clientObj->channelInfo.id, (int *)clientObj->userPtr, MEDIA_TYPE_CODEC_INFO, (char*)&mediainfo, NULL); } } }
断线状态的检测, 这里使用了一个时间对比的方式. 即用当前时间减去上一次获取到音视频流的时间,若是大于指定时长,则认为断线; oop
检查重连参数,若是须要重连,则销毁当前的全部对象,再建立新的对象, 继续开始新的循环url
if (NULL != pClient->rtspClient) { Medium::close(pClient->rtspClient); pClient->rtspClient = NULL; } if (NULL != pClient->env) { pClient->env->reclaim(); pClient->env = NULL; } if (NULL != pClient->scheduler) { delete pClient->scheduler; pClient->scheduler = NULL; } if (NULL != pClient->auth) { delete pClient->auth; pClient->auth = NULL; } if (NULL == pClient->scheduler) pClient->scheduler = BasicTaskScheduler::createNew(); if (NULL == pClient->scheduler) break; if (NULL == pClient->env) pClient->env = BasicUsageEnvironment::createNew(*pClient->scheduler); if (NULL == pClient->env) break; if (NULL == pClient->rtspClient) pClient->rtspClient = LiveRTSPClient::createNew(*pClient->env, pClient->channelInfo.url, RTSP_CLIENT_VERBOSITY_LEVEL, RTSP_CLIENT_NAME, 0, (void *)pClient); if (NULL == pClient->rtspClient) break;
今天主要概述了EasyRTSPClient的设计流程, 下一篇将开始着重讲解具体实现细节;线程
如下是我写的基于live555的两个应用:设计
EasyRTSPClient是一套很是稳定、易用、支持重连的RTSPClient工具,SDK形式提供,接口调用很是简单,不再用像调用live555那样处理整个RTSP OPTIONS/DESCRIBE/SETUP/PLAY的复杂流程,担忧内存释放的问题了,全平台支持(包括Windows/Linux 32&64,ARM各平台,Android,iOS),支持RTP Over TCP/UDP,支持断线重连,连续维护与迭代超过5年,可以接入市面上99%以上的IPC,调用简单且成熟稳定!
EasyIPCamera是一套很是稳定、易用、支持多种平台(包括Windows/Linux 32&64,Android,ARM hisiv100/hisiv200/hisiv400等平台)的RTSP Server组件,适用于IPCamera、内网RTSP服务等小型RTSP流媒体服务器,接口调用很是简单成熟,无需关注RTSPServer中关于客户端监听接入、音视频多路复用、RTSP具体流程、RTP打包与发送等相关问题,支持多种音视频格式,不再用像调用live555 RTSPServer那样处理整个RTSP OPTIONS/DESCRIBE/SETUP/PLAY/RTP/RTCP的复杂流程和担忧内存释放的问题了!
Copyright © EasyDarwin.org 2012-2017