承接上一节
udp服务器接流转html5播放

效果

先看效果:


服务器拉rtsp流,直接转成flv,不经过推流,浏览器使用ws直接连接写得我们写得服务器播放,因为websocket本身是跨域得,可以直接使用文件进行播放。http协议支持得时候注意要启动http服务支持,否则会跨域截断。

rtsp,rtp截流hack

上一章我们使用了udpserver来接流,也就是接得纯rtp,拼接成帧就行,而rtsp,和GB28181都使用rtp协议,【GB28181会使用ps流】,原理都一样,同样获取rtp流以后,可以直接转化成单帧再进行html5传输,如fmp4,或者转化成flv格式,使用flv.js来直接播放,flv内部也是转成了fmp4,区别不是很大。

1.1 截流描述

上一次我们使用了live555来接rtsp,live555接rtsp流,这样加上udp接就比较实用了,可以使用ffmpeg发送测试,也可以使用rtsp直接接入,rtsp连接写入配置文件中:in.txt

#id(int):address(varchar):width(int):height(int)
#418511899@qq.com author:钱波 qianbo 2021-02-28
1 rtsp://admin:hk123456@192.168.0.55/h264/ch1/sub/av_stream 1280 720 live/1001
#2 rtsp://127.0.0.1/2.264 1280 720 live/1001
#3 rtsp://127.0.0.1/1.264 640 360 live/1002

带# 得是注释,文件引入了一路海康流,输出流为live/1001

1.2流程

流程为:
1 线程rtsp client 拉到流后发送给flv服务器
2 flv服务器接收到连接后将连接放入到hub中,待接到rtsp sps pps等信息后开始发送meta信息,启动推流协程,并同步每个人得时间戳。注意每个人得时间戳是不一样得。
3 ws浏览器播放端退出在推流协程里面同步判断,退出则在hub中删除该端。

1.3 读配置文件类

struct s_file
{std::vector<s_source> v_sources;int func_read(){std::ifstream infile("in.txt", std::ios::in); //以文本模式打开in.txt备读if (!infile) { //打开失败std::cout << "error opening source file." << std::endl;return -1;}v_sources.clear();while (infile.good()) {string temp;s_source s;std::getline(infile, temp);if (temp.length() > 3 /*0xEF 0xBB 0xBF*/){uint8_t *pos = (uint8_t*)temp.c_str();if (*pos == 0xEF){temp = temp.substr(3);printf("%02x %02x %02x \n", *(pos), *(pos + 1), *(pos + 2));cout << "utf8 and BOM" << endl;}}//0xEF, 0xBB, 0xBF/*注意如果文件直接使用移入字符串,必须判断是否为结束,否则会多一行*///infile >> temp;//if (infile.eof())//    break;trim(temp);if (!ifnote(temp) && !temp.empty()){istringstream istr(temp);istr >>s.id >> s.v_address >> s.d_width >> s.d_height >>s.v_liveflv;v_sources.push_back(s);}else{//数据库解析字段}}return 0;}
};

isnote函数只是判断是否带有注释,注释则不加入其中,比较简单,读者可以自行写出。

1.4 websocket服务器

websocket服务器我们自行编写,使用协程方式来制作,这个在我得其他文章里面也提供了全部源代码,读者可以找一下。

1.5 flv服务器

显然flv服务器建立在websocket服务器之上,加了flv格式得封装,class 图如下图所示

class c_flvserver
{
private://websocket or httpasio::io_context &v_io_con_webs;//calculate the number of coroutinestd::atomic<uint32_t> v_coroutine_num = 0;public:/*int process_spspps(uint8_t * sps, uint32_t spslen,uint8_t * pps,uint32_t ppslen,uint32_t timestamp,int width, int height, int fps,uint32_t key);*/#if 0//关键帧再次同时写入sps和pps,特殊场合使用int process_h264_spspps(uint8_t *sps, int spslen,uint8_t *pps, int ppslen,uint8_t * nal,uint32_t nal_len,uint32_t timestamp,bool IsIframe);
#endifvoid storage_meta(uint32_t key,ptr_s_memory mem);int create_metadata(uint8_t* buf, int width, int height, int frameRate);int process_spspps(uint8_t * sps, uint32_t spslen,uint8_t * pps,uint32_t ppslen,uint32_t timestamp,uint32_t key);int process_spspps_sp(uint8_t * sps, uint32_t spslen,uint8_t * pps,uint32_t ppslen,uint32_t timestamp,uint32_t key);int process_h264(uint8_t * nal,uint32_t nal_len,uint32_t timestamp,bool IsIframe,uint32_t key);int process_aac(uint8_t* data, uint32_t data_len, uint32_t timestamp);c_flvserver(asio::io_context &iow) :v_io_con_webs(iow){}void start(uint16_t port);protected:
#ifdef SEND_META_SCRIPTint  create_metadata(uint8_t* buf, int width, int height, int frameRate);
#endifprotected:void storage_header(uint32_t key, int av, ptr_s_memory mem);void start_write_spawn(uint32_t key);bool func_set_head_send(tcp::socket &sock,uint8_t * buf, size_t buflen /*payloadlen*/, asio::yield_context &yield);//we must add the websockets head,use the func_set_head_sendint func_send_2session_webs(s_flvhub &flvhub,ptr_session_webs ptr,ptr_s_memory mem,asio::yield_context &yield);//we do not add ,just send the flv dataint func_send_2session_http(s_flvhub &flvhub,ptr_session_webs ptr,ptr_s_memory mem,asio::yield_context &yield);};

1.6 下面给出关键代码

只有一个流容易,只有一个客户也容易,我们面对得一定是多路流和多个客户并发连接,所以要注意得事项比较多,下面看具体代码:

int c_flvserver::func_send_2session_webs(s_flvhub &flvhub,ptr_session_webs ptr, ptr_s_memory mem,asio::yield_context &yield)
{if (!ptr->v_socket.is_open())return -2;DEFINE_ECuint8_t * data = mem->v_data;size_t len = mem->v_len;
#if 1if (!ptr->v_has_send_meta){uint8_t * _data = flvhub.v_meta->v_data;size_t _len = flvhub.v_meta->v_len;if (func_set_head_send(ptr->v_socket, _data, _len, yield) == false)return -1;ptr->v_has_send_meta = 1;}
#endifif (flvhub.v_need_video && !ptr->v_has_send_video_head){uint8_t * _data = flvhub.v_cache_headerv->v_data;size_t _len = flvhub.v_cache_headerv->v_len;if (func_set_head_send(ptr->v_socket, _data, (int)_len, yield) == false)return -1;ptr->v_has_send_video_head = 1;}if (flvhub.v_need_audio && !ptr->v_has_send_audio_head){uint8_t * _data = flvhub.v_cache_headera->v_data;size_t _len = flvhub.v_cache_headera->v_len;if (func_set_head_send(ptr->v_socket, _data, (int)_len, yield) == false)return -1;ptr->v_has_send_audio_head = 1;}if (!ptr->v_has_sent_key_frame){switch (*data) //the first byte{case 8://audio{cout << "audio waiting key frame." << endl;return 0;}break;case 9: //video{//fix me ,we must storage the key frame to the clientif (*(data+11 )== 0x17)  //0x27 not keyframe{cout << "find the keyframe" << endl;ptr->v_has_sent_key_frame = 1;//开始时间戳计算,meeveryptr->v_start_ts = GetTimestamp32();}else {cout << "...";return 0;}}break;default:return -1;break;}}
#if 1//change the timestamp,get the real stamp;uint32_t ts = GetTimestamp32() - ptr->v_start_ts;*(data + 4) =  (uint8_t)(ts >> 16);*(data + 5) =  (uint8_t)(ts >> 8);*(data + 6) =  (uint8_t)(ts);*(data + 7) =  (uint8_t)(ts >> 24);
#endif//flv_const_buffer bb(&header[0], 11, _data, _len);if (func_set_head_send(ptr->v_socket, data, (int)len, yield) == false)return -1;return 0;
}

以上是关键代码,下面给出一个代码结构,读者可以参考:


整个工程得代码并不多,比较简单,包含了flvserver,websocketserver,httpserver, rtp over udpserver,都使用协程制作,这样流程简单。包含rtsp得拉流客户端,比较实用,包含了analyse分析模块,可以对流进行图像分析等等,读者可以自行制作。

时间戳问题

如下图所示,明显vlc和ws连接得时间显然是不一样,ws连接时间很长,显示得时间竟然和vlc 相差20秒,这就是时间戳得问题了,所以要进一步处理该问题

如图,修正以后,时间戳趋于正常,flv播放比vlc rtsp 相差无几,快1秒左右,应该还有余地,可以在进行优化。

总结

本文并不使用拉流后再推流到服务端,而是将服务端直接集成,减少了部署内容,这是优点之一,第二个优点是并没有使用rtmp协议,而是直接转化成浏览器可播放得流,这是优点之二,缺点也很明显,读者可以提出讨论,或者有不明白得地方也可以讨论,知无不言言无不尽,第三篇我们可以加上rtsp服务,待续…

html测试代码

忘了html flv测试代码,加上了

rtsp,rtp,gb28181直接转化为html5播放(二)相关推荐

  1. html5播放rtsp h264视频流

    最近在研究html5实时播放rtsp流的问题,目前来说h5原生不支持这种格式,网上查了很多教程,大概有以下几种思路. rtsp转rtmp rtmp需要falsh的支持,但是在chrome已经默认禁用. ...

  2. ONVIF、RTSP/RTP、FFMPEG的开发实录

    ONVIF.RTSP/RTP.FFMPEG的开发实录 前言 本文从零基础一步步实现ONVIF协议.RTSP/RTP协议获取IPC实时视频流.FFMPEG解码.开发环境为WIN7 32位 + VS201 ...

  3. Wireshark 抓包分析 RTSP/RTP/RTCP 基本工作过程

    整体而言,RTSP 通常工作于可靠的传输协议 TCP 之上,就像 HTTP 那样,用于发起/结束流媒体传输,交换流媒体元信息.RTP 通常工作于 UDP 之上,用于传输实际的流媒体数据,其中的载荷格式 ...

  4. RTSP/RTP/RTCP协议的区别

    1. RTSP(Real-Time Streaming Protocol):实时流协议,它的出现是由于流媒体服务器的引入而出现的. 如上图所示,上图反映出的是常用地观看视频的过程.在浏览器中输入视频的 ...

  5. SkeyeVSS综合安防监控Onvif、RTSP、GB28181视频云无插件直播点播解决方案之监控视频实时多屏预览

    SkeyeVSS综合安防监控Onvif.RTSP.GB28181视频云无插件直播点播解决方案之监控视频实时多屏预览 SkeyeVSS支持一分屏.四分屏.九分屏.16分屏.25分屏.36分屏等几种N*N ...

  6. SkeyeVSS综合安防监控Onvif、RTSP、GB28181视频云无插件直播点播解决方案之子系统微服务集群解决方案

    SkeyeVSS综合安防监控Onvif.RTSP.GB28181视频云无插件直播点播解决方案之子系统微服务集群 我们通过SkeyeVSS系列文章<SkeyeVSS集群部署说明文档>可以了解 ...

  7. RTSP/RTP/RTCP协议流程及分析

    RTSP(实时流协议) RTSP中使用会话概念代替连接,由于它本身不与传输层绑定,因此RTSP会话在传输层支持TCP与UDP协议发送请求.RTSP客户机和服务器都可以发出请求,本身并不携带传输的媒体数 ...

  8. SkeyeVSS综合安防监控Onvif、RTSP、GB28181视频云无插件直播点播解决方案之监控视频云端录像无插件回放

    SkeyeVSS综合安防监控Onvif.RTSP.GB28181视频云无插件直播点播解决方案之监控视频云端录像无插件回放 SkeyeVSS通过接入SkeyeRMS录像服务器实现对接入系统的摄像机.NV ...

  9. SkeyeVSS综合安防监控Onvif、RTSP、GB28181视频云无插件直播点播解决方案之系统参数配置日志管理

    SkeyeVSS综合安防监控Onvif.RTSP.GB28181视频云无插件直播点播解决方案之系统参数配置日志管理 1.系统参数配置 SkeyeVSS系统参数配置页面如下图所示: 其中包括: 服务器名 ...

最新文章

  1. 用Visual Studio开发以太坊智能合约
  2. 找不到 快速启动 ,怎么办
  3. 编写程序计算 sentence 中有多少个单词,并指出其中最长和最短的单词。如果有多个最长或最短的单词,则将它们全部输出。
  4. Simulink工作区无法保存To workspace模块的数据解决办法
  5. leetcode589. N叉树的前序遍历
  6. django学习之路
  7. 标准C程序设计七---120
  8. 【iOS】彩虹渐变色 的 Swift 实现
  9. module 'scipy.misc' has no attribute 'imread' 报错解决
  10. PHP获取指定月份第一天、最后一天
  11. labview中DAQ采集多个数据通道(温度传感器)(TTL信号的曲轴位置传感器)总结
  12. android视频播放器课程设计,ANDROID视频播放器课程设计.pdf
  13. 无线通信学习笔记(三)
  14. 「2019.7.22 考试」AC和WA0一步之遥
  15. gimp 抠图_GIMP006:从简单抠图了解GIMP的浮动选区功能
  16. 小马哥服务器系统激活,Vue项目接口.md
  17. Alarm机制-学习记录
  18. LabVIEW如何打开Acrobat PDF文件
  19. microsoft office2016下载和安装
  20. 奥塔在线:Linux下按日期自动创建目录脚本

热门文章

  1. 证明人工智能的数据只要足够多,就可以接近理想效果
  2. powerbi内部部署安装指导
  3. [转]其实每个男孩都想做一个感情专一的好男人
  4. Google Ads支付宝付款功能正式上线
  5. 搭载“可信隐私沙盒”技术 蚂蚁集团联合荣耀手机从源头防范电信诈骗
  6. 十荟团关停全国业务 社区电商开启“降本增效”大突围
  7. 谷爱凌惊“险”一跳,最少价值10个亿!
  8. 有赞“小程序订阅消息”功能上线 支持商家主动推送「活动通知」
  9. 有点贵但卖光了!这款旗舰要火了吗...
  10. 快手:“我有一把大宝剑”