项目中处理接入流这块 需要加入SDK方面的一些扩展支持,这里说下海康的支持吧, 大华的同理。

从海康的SDK例子打开播放等等了解基本流程。

这里为了速度能够实时在海康的数据回调不用海康的解码SDK来处理而是自己接管。

例如大致下面:

auto fRealDataCallBack = [](LONG lRealHandle, DWORD dwDataType, BYTE* pBuffer, DWORD dwBufSize, void* pUser){switch (dwDataType){case NET_DVR_SYSHEAD:break;case NET_DVR_STREAMDATA:if (dwBufSize == 0 || pUser == 0)return;//TODO...break;}};

最后实际使用代码hknet_puller.h

#pragma once
#include "mpeg_puller.h"
#include "HCNetSDK.h"//拉流测试一路海康
class HKNetPuller :public InputElement
{
public:using InputElement::InputElement;//海康数据回调void dealData(uint8_t*& buf, int buf_size);
private:virtual void run(void) override;virtual bool open(void) override;virtual void close(void) override;virtual int read_AVPacket(AVPacket*& pkt);
private:bool hkPlay(void);void hkStop(void);
private:LONG lUserID;                   //注册设备LONG lRealPlayHandle;           //播放句柄
private:uint8_t* avio_ctx_buffer = nullptr;AVIOContext* pb = nullptr;CircularQueue streamQueue;      //缓存环形队列
public:PacketList* listPkts;virtual bool exportOpen(void){if (listPkts)listPkts->setCodecInfo(getCodecInfo());return true;};inline void setPacketListDatas(PacketList* datas){listPkts = datas;};
};//拉流后直接解码
class HKNetDecode :public HKNetPuller
{
public:using HKNetPuller::HKNetPuller;virtual int read_AVFrame(AVFrame*& frm){Global::freeAVFrame(frm);return 1;}
private:virtual int read_AVPacket(AVPacket*& pkt) override;FFDecode mCodec;
};//拉流解码应用
class HKNetDecodePull :public HKNetDecode
{
public:using HKNetDecode::HKNetDecode;
public:virtual bool exportOpen(void){if (listFrms)listFrms->setCodecInfo(getCodecInfo());return true;};virtual int read_AVFrame(AVFrame*& frm);//下面是frame数据管理 ???FrameList* listFrms;inline void setFrameListDatas(FrameList* datas){listFrms = datas;};
};

实现部分


#include "stdafx.h"
#include "hknet_puller.h"
#include <chrono>
#ifdef WIN32
#pragma comment(lib,"HCCore.lib")
#pragma comment(lib,"HCNetSDK.lib")
#endif using namespace std::chrono;
const int BUF_SIZE = 1024 * 16;void HKNetPuller::run(void)
{while (threadStatus){//1-打开连接处理if (!open()){close();std::this_thread::sleep_for(std::chrono::milliseconds(500));continue;}resetContextTimer();//2-取pkt数据AVPacket* pkt = av_packet_alloc();iRet = av_read_frame(pFormatCtx, pkt);//3-检查处理视频 处理重连机制if (iRet < 0){Global::freeAVPacket(pkt);if (iRet == AVERROR_EOF || !pFormatCtx->pb || avio_feof(pFormatCtx->pb) || pFormatCtx->pb->error)close();continue;}//4-回调出去 在外面处理if (pkt->stream_index != vindex){Global::freeAVPacket(pkt);continue;}read_AVPacket(pkt);//5-waitiFrameIndex++;//固定频率std::this_thread::sleep_for(std::chrono::milliseconds(5));}close();
}bool HKNetPuller::open(void)
{if (isOpened)return true;if (!streamQueue.init(0, 2 * 1024 * 1024)){ErrorLog << " init stream queue is failed";return false;}//海康播放if (!hkPlay())return false;//ffmpeg-------------------------------avio_ctx_buffer = (uint8_t*)av_malloc(sizeof(uint8_t) * BUF_SIZE);if (!avio_ctx_buffer){ErrorLog << "av_malloc ctx buffer failed!";return false;}//ffmpeg打开流的回调auto onReadData = [](void* pUser, uint8_t* buf, int bufSize)->int{HKNetPuller* pHkPuller = (HKNetPuller*)pUser;if (!pHkPuller)return -1;auto startTime = steady_clock::now();do{int readLen = pHkPuller->streamQueue.popdata(buf, bufSize);if (readLen > 0)return readLen;else if (readLen < 0)return -1;else{int passed = duration_cast<milliseconds>(steady_clock::now() - startTime).count();if (passed > 5000){ErrorLog << " Read No Data for " << passed << "ms";return -1;}}} while (true);return 0;};pb = avio_alloc_context(avio_ctx_buffer, BUF_SIZE, 0, this, onReadData, nullptr, nullptr);if (pb == nullptr)  //分配空间失败{if (avio_ctx_buffer)av_freep(&avio_ctx_buffer);ErrorLog << "avio_alloc_context failed";return false;}//等待数据包auto startTime = steady_clock::now();while (1){if (streamQueue.getsize() > 100000)break;int passed = duration_cast<milliseconds>(steady_clock::now() - startTime).count();if (passed > 15000) {ErrorLog << " wait source stream failed " << passed << "ms";return false;}}AVDictionary* opts = nullptr;av_dict_set(&opts, "fflags", "nobuffer", 0);av_dict_set(&opts, "max_analyze_duration", "10", 0);av_dict_set(&opts, "max_delay", "1000", 0);av_dict_set(&opts, "stimeout", "1000000", 0);av_dict_set(&opts, "probesize", "4096", 0);             //加快打开//下面处理ffmpeg api创建createTimeContext(&pFormatCtx);pFormatCtx->pb = pb;if ((iRet = avformat_open_input(&pFormatCtx, "", nullptr, &opts)) < 0){ErrorLog << "Could not open input file: " << getUrl();if (nullptr != opts)av_dict_free(&opts);return false;}if (nullptr != opts)av_dict_free(&opts);if ((iRet = avformat_find_stream_info(pFormatCtx, nullptr)) < 0){ErrorLog << "Failed to avformat_find_stream_info: " << getUrl();return false;}av_dump_format(pFormatCtx, 0, nullptr, 0);//分析流信息if (!getvideoindex())return false;tmBegin = std::chrono::steady_clock::now();iFrameIndex = 0;isOpened = true;return true;
}void HKNetPuller::close(void)
{hkStop();if (pb){if (pb->buffer)av_freep(&pb->buffer);avio_context_free(&pb);}streamQueue.reset(true);avformat_close_input(&pFormatCtx);avformat_free_context(pFormatCtx);streamQueue.fini();vindex = aindex = -1;isOpened = false;
}int HKNetPuller::read_AVPacket(AVPacket*& pkt)
{if (listPkts){auto packet = std::make_shared<PacketData>(pkt);listPkts->pushData(packet);return 1;}else {DebugLog << "listPkts is null!   freeAVPacket";Global::freeAVPacket(pkt);      //释放pktreturn 0;}
}int dumpBuff(BYTE* buff,int iSize)
{std::cout << ">> 264" << std::endl;FILE* fp = nullptr;char fileName[255];sprintf(fileName, "packet.h264");fp = fopen(fileName, "ab");     //二进制追加写入if (fp == nullptr)return 0;fwrite(buff, 1, iSize, fp);fclose(fp);return 1;
}bool HKNetPuller::hkPlay(void)
{// 初始化NET_DVR_Init();// 登录NET_DVR_DEVICEINFO_V30 struDeviceInfo;lUserID = NET_DVR_Login_V30("192.168.77.113", 8000, "admin", "admin12345", &struDeviceInfo);//lUserID = NET_DVR_Login_V30("192.168.77.190", 8000, "admin", "Admin12345", &struDeviceInfo);if (lUserID < 0){printf("Login error, %d\n", NET_DVR_GetLastError());NET_DVR_Cleanup();return false;}//---------------------------------------//启动预览并设置回调数据流NET_DVR_CLIENTINFO ClientInfo = { 0 };ClientInfo.hPlayWnd = nullptr;      //需要SDK解码时句柄设为有效值,仅取流不解码时可设为空ClientInfo.lChannel = 1;            //预览通道号ClientInfo.lLinkMode = 0;           //最高位(31)为0表示主码流,为1表示子码流0~30位表示连接方式:0-TCP方式;1-UDP方式;2-多播方式;3-RTP方式;ClientInfo.sMultiCastIP = nullptr;  //多播地址,需要多播预览时配置//海康的回调auto fRealDataCallBack = [](LONG lRealHandle, DWORD dwDataType, BYTE* pBuffer, DWORD dwBufSize, void* pUser){switch (dwDataType){case NET_DVR_SYSHEAD:break;case NET_DVR_STREAMDATA:if (dwBufSize == 0 || pUser == 0)return;static int kk = 0;if (kk++ < 500)dumpBuff(pBuffer, dwBufSize);HKNetPuller* streamSender = (HKNetPuller*)(pUser);if (streamSender)streamSender->dealData(pBuffer, dwBufSize);  //丢给环形缓存break;}};lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, fRealDataCallBack, this, (BOOL)true);if (lRealPlayHandle < 0){printf("NET_DVR_RealPlay_V30 error, %d\n", NET_DVR_GetLastError());NET_DVR_Logout(lUserID);NET_DVR_Cleanup();return false;}return true;
}void HKNetPuller::hkStop(void)
{//关闭预览NET_DVR_StopRealPlay(lRealPlayHandle);//注销用户NET_DVR_Logout_V30(lUserID);NET_DVR_Cleanup();
}void HKNetPuller::dealData(uint8_t*& buf, int buf_size)
{int32_t len = buf_size;int32_t total_read = 0;uint8_t* dbuf = buf;int32_t ret = 0;int emptyCount = 0;do{len = buf_size - total_read;ret = streamQueue.pushdata(dbuf, buf_size);if (ret == 0){emptyCount++;if (emptyCount >= 10){if (total_read > 0)return ;return;}}else if (ret < 0)return ;elseemptyCount = 0;total_read += ret;dbuf += ret;} while (total_read < buf_size);
}int HKNetDecode::read_AVPacket(AVPacket*& pkt)
{mCodec.setAVCodecParameter(getCodecInfo()->getAVCodecParam());//解码模块处理解码AVFrame* pFrame = mCodec.decode(pkt);Global::freeAVPacket(pkt);if (pFrame != nullptr){read_AVFrame(pFrame);return 1;}return 0;
}int HKNetDecodePull::read_AVFrame(AVFrame*& frm)
{if (listFrms){auto frame = std::make_shared<FrameData>(frm);listFrms->pushData(frame);//Global::freeAVFrame(frm);      //下级释放return 1;}else {Global::freeAVFrame(frm);return 0;}return 1;
}

最后代码放 http://hamiguax.gicp.net/play/hkstream.git

ffmpeg海康SDK流接入的支持相关推荐

  1. 标准协议支持RTMP、RTSP、GB/T28181、海康SDK、Ehome平台接入互联网安防视频融合云服务EasyCVR如何接入海康硬盘录像机?

    关于TSINGSEE青犀视频的视频网关服务,常见的接入设备包括摄像头和硬盘录像机,其中也以海康品牌为主,不少用户是在局域网部署了摄像头,又部署了硬盘录像机,需要将硬盘录像机接入到我们的视频网关中来.在 ...

  2. AI云边端协同EasyCVR使用海康SDK接入,设备录像下载失败是什么原因?

    EasyCVR视频融合云服务支持多协议.多类型的设备接入,平台具备强大的视频汇聚与管理.数据分发.平台级联.设备管理等视频能力.基于云边端架构,EasyCVR具备很灵活的云边调度能力,解决视频监控领域 ...

  3. 海康sdk捕获码流数据通过JavaCV推成rtmp流的实现思路(PS流转封装RTMP)

    海康sdk捕获码流数据通过JavaCV推成rtmp流的实现思路(PS流转封装RTMP) 问题分析 转码推rtmp PS流转封装 码云(Gitee)主页:https://gitee.com/banmaj ...

  4. RTSP/RTMP/GB28181协议/海康SDK/Ehome协议接入TSINGSEE青犀视频平台磁盘空间计算介绍

    通常情况下,RTSP/RTMP/GB28181协议/海康SDK/Ehome协议接入TSINGSEE青犀视频平台录制的视频流都是存储在磁盘当中,我们之前讲过磁盘空间是否满足剩余的要求的方法,具体实现方式 ...

  5. 海康视频监控接入心得

    由于业务需要接入海康视频监控,目前有几种办法: web接入,就是html+js+海康component.exe接入,可找海康邮箱索要开发包及文档: sdk接入,海康官网下载sdk,有demo可直接使用 ...

  6. 海康SDK/大华SDK安防视频智能分析平台EasyCVR如何将通道视频流推送至CDN分发?

    EasyCVR视频协议融合平台不仅支持常规协议的接入,我们还拓展了海康SDK.大华SDK.Ehome等私有协议.如果前端设备协议不同且数量较多,则可以通过EasyCVR平台来对所有视频通道做整合和统一 ...

  7. 海康Ehome协议接入EasyCVR视频融合平台播放视频失败的排查与解决

    EasyCVR视频融合平台的视频能力非常灵活,尤其是在接入协议上,不仅能支持主流的标准协议,如国标GB/T28181.RTSP/Onvif.RTMP等,还可以支持厂家的私有协议,包括海康Ehome.海 ...

  8. 海康sdk项目部署Linux系统时出现java.lang.UnstisfiedLinkError:jnidispatch(xxx)not found in resource path错误

    海康sdk项目部署Linux系统时出现java.lang.UnstisfiedLinkError:jnidispatch(xxx)not found in resource path错误 问题描述 解 ...

  9. Android平台上集成海康SDK(二)

    Android平台上集成海康SDK 以上是我之前写的一篇Android平台上集成海康SDK的文章,其中对于Android平台上集成海康SDK.基于海康SDK进行二次开发基本上进行了详细地介绍. 这篇文 ...

  10. 海康SDK开发实时读取摄像头图像

    1.概述 最近项目需要实时读取网络摄像头,并对图像做处理,参考网络资料和海康SDK开发文档,文档中给了两种方式(1)SDK直接解码显示(2)实时流数据回调,用户自行处理码流数据(开发文档上以软解显示为 ...

最新文章

  1. MindSpore Lite整体架构介绍
  2. BERT+CRF的损失函数的研究
  3. 遍历jenkins build后的文件夹,找出最新“build NO.”复制到制定目录进行操作
  4. block 与 dispatch quene
  5. 运维进化论:微盟“删库跑路”给我们的启示
  6. 使用Selenium自动化测试处理多个浏览器选项卡
  7. vue swiper循环播放无效解决
  8. php2twig,symfony2 twig模板引擎,symfony2twig模板_PHP教程
  9. 计算机基础教程2 - 计算机发展历程
  10. JavaScript 封装设计模式介绍
  11. Redis Cluster 的安装和配置(1)
  12. HBuilder实现WiFi调试Android
  13. rematch简单使用
  14. 三层架构(网络冗余学习)
  15. Windows 10 无法访问共享的解决办法
  16. vue导出excel加一个进度条_运用vue导出excel碰到的那些坑
  17. qprocess qt 打开word_Qt QProcess启动和关闭外部程序
  18. SpringBoot物流管理项目,拿去学习吧(源码)
  19. android 抽屉组件,Android组件之DrawerLayout实现抽屉菜单
  20. 微信 html自动复制功能,怎样在网页中一键复制拷贝微信号跳转到微信

热门文章

  1. 微型计算机原理及应用论文,微机原理及应用结业论文
  2. HTML超好看的个人主页源码+支持响应式
  3. 混响时间测试软件安卓版,混响时间的测量方法资料.pdf
  4. 谷歌推出全能扒谱AI:只要听一遍歌曲,钢琴小提琴的乐谱全有了
  5. selnium 判断页面加载完成_Selenium 的页面加载以及几种等待的问题
  6. 超星阅读器pdz文件转为xps文件或pdf文件说明
  7. 自己动手简单实现vbb的URL静态化
  8. 初学者怎样快速学会 SQL
  9. centos linux引导修复_CentOs7 修复 引导启动
  10. win+ubuntu系统引导修复