高复用率的RTSPClient组件EasyRTSPClient设计流程概述
EasyRTSPClient 设计过程
概述
EasyRTSPClient 基于live555构建而成. 今天讲讲EasyRTSPClient的设计过程
EasyRTSPClient,主要包括以下部分:
1. 创建live555对象, 连接相机和收流
2. 解析收到的视频分辨率
3. 将SDP、音视频流、分辨率及其它相关信息通过回调函数进行回调
4. 回调连接、断线状态
5. 根据参数执行是否重连
创建live555对象,连接相机和收流
网上很多介绍的都是使用testRTSPClient来做客户端, 这个是没有问题的,但有一点需要注意的是demo中的代码,都是阻塞式的,如下:
env->taskScheduler().doEventLoop(&eventLoopWatchVariable);
这样就在主线程中阻塞了, 如果我需要它退出,该怎样实现呢?
有两种方法,目的是相同的,实现方式略有不同罢了:
1. 外部改变eventLoopWatchVariable的值为1
2. 通过BasicTaskScheduler0::doEventLoop(char* watchVariable)的实现可以看出, 这里实际上是进行一个无限循环. 当 watchVariable的值不为0时就退出. 所以我们可以自己创建一个线程,在线程内部实现调用 pTaskScheduler0->SingleStep(0), 即可实现对该线程的自由控制; 相当于1个线程对应1路到摄像机的取流;
解析视频分辨率
解析分辨率主要是sps_pps.h .c实现,是从VLC中提取出来的相关代码, 可正常解析H264,H265的分辨率;
回调SDP, 音视频流,分辨率及其它相关信息
在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);
}
}
}
回调连接、断线状态
断线状态的检测, 这里使用了一个时间对比的方式. 即用当前时间减去上一次获取到音视频流的时间,如果大于指定时长,则认为断线;
根据参数执行是否重连
检查重连参数,如果需要重连,则销毁当前的所有对象,再创建新的对象, 继续开始新的循环
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
EasyRTSPClient是一套非常稳定、易用、支持重连的RTSPClient工具,SDK形式提供,接口调用非常简单,再也不用像调用live555那样处理整个RTSP OPTIONS/DESCRIBE/SETUP/PLAY的复杂流程,担心内存释放的问题了,全平台支持(包括Windows/Linux 32&64,ARM各平台,Android,iOS),支持RTP Over TCP/UDP,支持断线重连,连续维护与迭代超过5年,能够接入市面上99%以上的IPC,调用简单且成熟稳定!
关于EasyIPCamera
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

高复用率的RTSPClient组件EasyRTSPClient设计流程概述的更多相关文章
- 高复用率的RTSPClient组件EasyRTSPClient调用说明
EasyRTSPClient 调用说明 概述 EasyRtspClient是EasyDarwin家族中针对RTSP协议的拉流组件 EasyRtspClient视频支持H264.H265.MJPEG格式 ...
- IC设计流程概述
芯片设计分为前端设计和后端设计,前端设计(也称逻辑设计)和后端设计(也称物理设计)并没有统一严格的界限,涉及到与工艺有关的设计就是后端设计. Front-end design flow 1. 规格制定 ...
- 通用异步 Windows Socket TCP 客户端组件的设计与实现
编写 Windows Socket TCP 客户端其实并不困难,Windows 提供了6种 I/O 通信模型供大家选择.但本座看过很多客户端程序都把 Socket 通信和业务逻辑混在一起,剪不断理还乱 ...
- 基于 IOCP 的通用异步 Windows Socket TCP 高性能服务端组件的设计与实现
设计概述 服务端通信组件的设计是一项非常严谨的工作,其中性能.伸缩性和稳定性是必须考虑的硬性质量指标,若要把组件设计为通用组件提供给多种已知或未知的上层应用使用,则设计的难度更会大大增加,通用性.可用 ...
- 微服务架构案例(05):SpringCloud 基础组件应用设计
本文源码:GitHub·点这里 || GitEE·点这里 更新进度(共6节): 01:项目技术选型简介,架构图解说明 02:业务架构设计,系统分层管理 03:数据库选型,业务数据设计规划 04:中间件 ...
- Steps 组件的设计与实现
NutUI 组件源码揭秘 前言 本文的主题是 Steps 组件的设计与实现.Steps 组件是 Steps 步骤和 Timeline 组件结合的组件,在此之前他们是两个不同的组件,在 NutUI 最近 ...
- ASP.NET通用权限组件思路设计
开篇 做任何系统都离不开和绕不过权限的控制,尤其是B/S系统工作原理的特殊性使得权限控制起来更为繁琐,所以就在想是否可以利用IIS的工作原理,在IIS处理客户端请求的某个入口或出口通过判断URL来达到 ...
- Unity3d&C#分布式游戏服务器ET框架介绍-组件式设计
前几天写了<开源分享 Unity3d客户端与C#分布式服务端游戏框架>,受到很多人关注,QQ群几天就加了80多个人.开源这个框架的主要目的也是分享自己设计ET的一些想法,所以我准备写一系列 ...
- Java高并发 -- J.U.C.组件扩展
Java高并发 -- J.U.C.组件扩展 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 FutureTask Future模式,核心思想是异步调用.和同步调用的区别 ...
随机推荐
- DB2数据库报 [SQL0805N Package "NULLID.SQLLD003" was not found.]
解决办法: cd /home/db2inst1/sqllib/bnddb2 bind @db2cli.lst blocking all grant public sqlerror continue C ...
- HDU 1998 奇数阶魔方【模拟填数/注意边界和细节】
奇数阶魔方 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- bjtu 1846. Infinity的装备[状压dp+dfs/bfs]
https://citel.bjtu.edu.cn/acm/oj/problem/1846 1846. Infinity的装备 时间限制 1000 ms 内存限制 64 MB 题目描述 “测试服终于下 ...
- TopCoder SRM 301 Div2 Problem 1000 CorrectingParenthesization(区间DP)
题意 给定一个长度为偶数的字符串.这个字符串由三种括号组成. 现在要把这个字符串修改为一个符合括号完全匹配的字符串,改变一个括号的代价为$1$,求最小总代价. 区间DP.令$dp[i][j]$为把子 ...
- Codeforces 746G New Roads (构造)
G. New Roads ...
- Apache Openwhisk学习(一)
一.背景 最近中途参与的一个项目是和Serverless.Faas相关的,项目的整体架构和实现都参考了开源项目openwhisk,因此,同事们在编码时都会参考openwhisk的源码.因为以前从没有接 ...
- 无法获得VMCI 驱动程序的版本: 句柄无效。
写在前面 最近在电脑上安装了VMware虚拟机,在安装系统的使用,总提示错误“无法获得VMCI 驱动程序的版本: 句柄无效.”.最近刚买的电脑,也不会是系统的问题吧,为了装个虚机,总不能重装系统吧,没 ...
- sencha toucha获取 constructor中的数据
config:{ tmp:null }, constructor : function(conf) { this.config.tmp=conf; } 添加配置属性,然后直接用 this.config ...
- Linux内核中等待队列的几种用法
Linux内核里的等待队列机制在做驱动开发时用的非常多,多用来实现阻塞式访问,下面简单总结了等待队列的四种用法,希望对读者有所帮助. 1. 睡眠等待某个条件发生(条件为假时睡眠): 睡眠方式:wait ...
- 线程中的WaitForSingleObject和Event的用法
http://chinaxyw.iteye.com/blog/548622 首先介绍CreateEvent是创建windows事件的意思,作用主要用在判断线程退出,程锁定方面. CreateEvent ...