GB28181

GB28181 是我国内的标准,现在到2016修订后比较成熟,有很多可取之处,当然,依然是建立在sip协议之上,比起rtmp协议来说,他的优点是复用了rtp协议和sdp协议,这一点很优秀,也解决了很多问题。

ps流

ps流严格来说是适合传输的文件流。例如海康大华的GB28181 的ps流,事实上,用ffmpeg也是可以探测ps流的,准备好一个类,叫IOThread,从TThread类继承,这个类后面给出,只是为了简单启动一个线程,也不一定要这么写,完全是为了示例。

class IOThread :public TThread
{uint8_t* pIObuffer = NULL;AVIOContext* pb = NULL;AVInputFormat* piFmt = NULL;AVFormatContext* pFormatContext = NULL;unsigned int video_stream_index;queue<RTPPacket*> _queue;void *_RTPSession = NULL;std::mutex  _mutex;int64_t framebytes = 0;class Lock {private:std::lock_guard<std::mutex> m_lock;public:inline Lock(IOThread* parent) : m_lock(parent->_mutex) {}};
public:static int fill_iobuffer(void* opaque, uint8_t* buf, int bufSize);
public:/*void AddBytes(int len){framebytes += len;}*/int64_t GetBytes(){return framebytes;}void InitProbe(void *param);int  ReadNetPacket(uint8_t *buf, int buf_size);void Push(RTPPacket * pkt);void Run();
};

具体实现,这只是个技术示例,展示用,实际使用请写好,自行修改!

//因为可能启动多个IOThread
int IOThread::fill_iobuffer(void* opaque, uint8_t* buf, int bufSize)
{IOThread * IOB = (IOThread*)opaque;return  IOB->ReadNetPacket(buf, bufSize);
}//初始化探测器,每一路流都有一个探测器
void IOThread::InitProbe(void *param)
{_RTPSession = (MyRTPSession*)param;
}
void IOThread::Push(RTPPacket * pkt)
{//Lock lock(this);if (IsStop())return;Lock lock(this);_queue.push(pkt);
}int IOThread::ReadNetPacket(uint8_t *buf, int buf_size)
{//rtp协议优化,一次读取两个到几个包
#define READ_PKT_NUM 3int nsize = 0;for (int i = 0; i < READ_PKT_NUM; i++){std::this_thread::sleep_for(std::chrono::milliseconds(5));Lock lock(this);if (_queue.empty())break;RTPPacket * pkt = _queue.front();_queue.pop();int plen = pkt->GetPayloadLength();memcpy(buf+nsize, pkt->GetPayloadData(), plen);nsize += plen;((MyRTPSession*)(_RTPSession))->DeletePacket(pkt);}return nsize;
}void IOThread::Run()
{if (_RTPSession == NULL) {printf("session is null\n");return;}//这里需要修正的是:如果一开始接收到的不是关键帧,前面开始过,没有停止//等待50毫秒while (1){if (IsStop())return;if (_queue.size() < READ_PKT_NUM){std::this_thread::sleep_for(std::chrono::milliseconds(5));}elsebreak;}//先clock_t start, end,end2;start = clock();//缓存大小 看定义PKT_NUM
#define BUFFER_IO_LEN READ_PKT_NUM*1500pIObuffer = (uint8_t*)av_malloc(BUFFER_IO_LEN);pb = avio_alloc_context(pIObuffer,BUFFER_IO_LEN,0,this,fill_iobuffer,NULL,NULL);if (av_probe_input_buffer(pb, &piFmt, "", NULL, 0, 0) < 0)//探测从内存中获取到的媒体流的格式{printf("Error: probe format failed\n");return;}//printf("input format:%s[%s]\n", piFmt->name, piFmt->long_name);pFormatContext = avformat_alloc_context();pFormatContext->pb = pb;pFormatContext->flags = AVFMT_FLAG_CUSTOM_IO;pFormatContext->max_analyze_duration = 1000000;pFormatContext->fps_probe_size = 5;//AVInputFormat* pInputFormat = NULL;//pInputFormat = av_find_input_format("h264");//int ret = avformat_open_input(&pFormatContext, "", pInputFormat, NULL);int ret = avformat_open_input(&pFormatContext, "", piFmt, NULL);if (ret < 0){printf("Error: avformat_open_input failed----------------- \n");//ASSERT(0);return;}end = clock();printf("avformat_open_input() used time: %ld ms \n", start - end);ret = avformat_find_stream_info(pFormatContext, NULL);if (ret < 0){printf("Error: avformat_find_stream_info failed----------------- \n");return;}for (int i = 0; i < pFormatContext->nb_streams; i++){if (AVMEDIA_TYPE_VIDEO == pFormatContext->streams[video_stream_index]->codecpar->codec_type){video_stream_index = i;//avCodecID = pFormatContext->streams[video_stream_index]->codec->codec_id;break;}}end2 = clock();printf("avformat_find_stream_info() used time: %ld ms\n", end2- start);#if 1//char filename[MAX_PATH];//_snprintf(filename, 128, "qianbo_ffmpeg.264");FILE * fp = fopen("qianbo_ffmpeg.264", "wb");
#endif//fwrite(data, 1, len, fp);AVPacket packet;while (1){if (IsStop())break;std::this_thread::sleep_for(std::chrono::milliseconds(20));av_init_packet(&packet);if (av_read_frame(pFormatContext, &packet) == 0) { //读成功if (packet.stream_index == video_stream_index){uint8_t * data = packet.data;//char buffer[256];//sprintf(buffer, "%02x %02x %02x %02x %02x %02x len : %d", data[0], data[1], data[2], data[3], data[4], data[5], packet.size);//printf("%s\n",buffer);fwrite(data, 1, packet.size, fp);}av_packet_unref(&packet);}}av_free(pIObuffer);
#if 1fclose(fp);#endif
}

thread类

#ifndef _TTHREAD_RUN_ABLE_H_
#define _TTHREAD_RUN_ABLE_H_#include <mutex>
#include <queue>
#include <thread>
#include <atomic>
#include <condition_variable>
using namespace std;class TThread
{private://线程thread _thread;//等待信号std::mutex _signal_mutex;std::condition_variable _cond;
protected:volatile char _stop = true;//锁定运行状态std::mutex _mutex;
public:TThread(){}virtual ~TThread(){}public:void Join(){if (_thread.joinable())_thread.join();}bool  IsStop(){return _stop == 1 ? true : false;}void WaitForSignal(){std::unique_lock<std::mutex> ul(_signal_mutex);_cond.wait(ul);}void Notify(){_cond.notify_one();}virtual int Start(){if (_stop == 0)return -1;_stop = 0;_thread = std::thread(std::bind(&TThread::Run, this));return 0;}  virtual void Stop(){//先通知,后停止Notify();_stop = 1; // true;}virtual void Run() = 0;};
#endif

以上就是使用ffmepg来探测流的过程,不详细说明,实践动手就行,这个方式也是比较好的,因为ffmpeg还是可以帮我们屏蔽一些细节,为了达到效果,还是要认真了解ps流,也需要了解各个不同厂家的ps流的详细不同情况。

感谢您看我的文章。

使用ffmpeg来探测GB28181的ps流相关推荐

  1. Gb28181之Ps流解析H264

    gb28181发送码流选择PS流,PS流在封装H264的数据.本文详细描述如何通过ps流解析H264码流. *************************PSM流解析*************** ...

  2. 最简单的GB28181视频PS流播放器。

    一 从PS流中提取h264和aac. 移步:https://blog.csdn.net/qq_39805297/article/details/107083322 二 基于ffmpeg解码h264获取 ...

  3. ffmpeg添加mpeg ps流的pcm的解码支持

    ffmpeg原本不支持mpeg ps流,原因有两个.首先在编码时,ffmpeg没有在流中写入psm头:其次,在解码时,只在读文件头的时候判断了流的类型,而ps流中,流类型是在psm头中的,这样ffmp ...

  4. 海康摄像头PS流格式解析(RTP/PS/H264)

    海康威视视频录像以PS格式打包,解析的过程按照PS包-->system header--->program stream map--->音视频PES包一路下来,海康在包中自定义了一些 ...

  5. javaCV简单解析gb28181的rtp ps流,并推流到rtmp服务

    本文转自javacv社区三群管理员"赶在时间前面":过去的过去了的博客,感谢大佬倾情贡献,支持javacv社区发展和壮大. 国标gb28181全系列都可以参考过去的过去了的博客,再 ...

  6. ffmpeg解码ps流部分代码以及PS播放器demo

    之前的设备研发算是告一段落了,最近一直在忙视频监控平台的架构以及实现,想把自己的设备接到自己的平台里,设备上的码流是ps流,要在平台里解码ps流->解码成h264->yuv->rgb ...

  7. PS流(ISO13818和GB28181)分析

    1.理论基础: PSM(PS System map)提供了对PS流中的原始流和他们之间的相互关系的描述信息:PSM是作为一个PES分组出现,当stream_id == 0xBC时,说明此PES包是一个 ...

  8. ps流 转发_VAG.Node: GB28181 信令服务服务,支持PS流到RTMP流的转码和转发功能

    VAG.Node GB28181 VAG(Video Agent Gateway) ,主要应用将 GB28181协议 摄像机/硬盘录像机 的PS流(H264/H265)打包推送到RTMP服务器发布. ...

  9. gb28181简单解包rtp ps流,推出rtmp(java版基于springboot):六、解包rtp ps流,推出rtmp

    解析流程参考 https://blog.csdn.net/chen495810242/article/details/39207305 代码基于github上的修改 https://github.co ...

最新文章

  1. Python 3 利用 subprocess 实现管道( pipe )交互操作读/写通信
  2. 二叉搜索树的第k个节点java_剑指Offer62:二叉搜索树的第k个结点(Java)
  3. 简单的html5,简单的HTML5初步入门教程
  4. 从零实现来理解机器学习算法:书籍推荐及障碍的克服
  5. python flask 部署_python flask 部署
  6. boost::hana::replace用法的测试程序
  7. matlab生成随机粗糙表面_随机粗糙面建模
  8. 最稳妥的服务器阵列方案:RAID5+热备盘
  9. python检测输入文本的语言
  10. python进阶08并发之四map, apply, map_async, apply_async差异
  11. alert确认后执行_微任务、宏任务、DOM渲染的执行顺序
  12. [BZOJ1045] [HAOI2008] 糖果传递 (中位数)
  13. 双人成行本地安装X360ce模拟手柄教程xpadder手柄模拟键盘鼠标
  14. 管螺纹如何标注_天天和螺纹打交道,你知道有多少种螺纹吗,原来螺纹种类这么乱...
  15. python凹多边形分割_凹多边形拆分
  16. 按键精灵卡屏检测判断窗口是否无响应或卡屏
  17. 基于C++的高性能http框架cinatra及其web框架示例feather介绍及开发演示
  18. 【火炉炼AI】机器学习031-KNN回归器模型的构建
  19. [从头读历史] 第309节 星球战争 BC2499 至 BC2400(公元前25世纪)
  20. php同子域单点登录,SSO 单点登录总结(PHP)(示例代码)

热门文章

  1. wgs84坐标系转换工具_ArcGIS中不同坐标系之间的转换
  2. python中的命名空间指什么_python中命名空间
  3. 中国电信:预计2021年归母净利润同比增长23%-25%
  4. 2022年春运火车票明起开卖
  5. 一条视频涨粉百万,主角却不是人?!
  6. 三星显示、LG已开始为苹果iPhone 13生产OLED屏幕
  7. 降价到心痛也无人问津!这款手机成绝唱...
  8. 滚蛋吧,2020的糟心事儿!2021,先“拼”为敬!
  9. 华为nova 8系列发布日期曝光:售价还卖贵点?
  10. 华为Mate 40 Pro维修价来了:这个部件最贵,够买一部顶级旗舰