zoukankan      html  css  js  c++  java
  • 安防融合视频云服务EasyCVR集成海康EHome协议实现设备录像回看返回会话ID为-1是什么情况?

    之前TSINGSEE青犀视频讲过互联网安防视频云服务EasyCVR能够集成海康EHome私有协议,当然我们在测试的时候碰到了一些问题,本文就来讲一下测试EasyCVR集成海康EHome协议实现设备录像回看时遇到的问题。

    一、测试环境

    • 设备型号DS-2CD2325FD-XF2005
    • SDK 版本 HCISUPSDKV2.3.4.2_build20200316_Win64_ZH

    二、问题描述

    1、 按照官方文档介绍,开启监听服务后,启播设备录像将返回一个会话ID,应用层可以将这个会话ID与播放操作进行绑定。

    69.png

    实际使用过程中会话ID 一直为无效值-1.

    2、设备录像回看需启用回放监听服务不能与直播预览共用

    3、设备录像每次触发的回调不是pes,也就是接收的包起始不是0x000001

    三、解决方案

    1、应用层设备录像播放接口,添加操作队列,同时只能启播一个设备录像,将启播成功取流回调中的句柄与设备录像进行绑定。

    2、设备录像回看需启用流媒体服务器(SMS)的回放监听并注册回调函数以接收设备连接请求,如果想实现多路设备录像回看,最好每一路设备录像启用一个回放监听服务。

    3、应用层添加缓存,进行流分割,获取一个完整的ps包后再进行解复用流程

    #include <stdio.h>
    #include <Windows.h>
    #include "HCISUPCMS.h"
    #include "HCISUPStream.h"
    #include "plaympeg4.h"
     
    LONG lLoginID = -1;
    LONG lLinkHandle = -1;
    LONG lPlayHandle = -1;
    FILE *Videofile = NULL;
     
    //
    //注册回调函数
    BOOL CALLBACK RegisterCallBack(LONG lUserID, DWORD dwDataType, void *pOutBuffer, DWORD dwOutLen, void *pInBuffer, DWORD dwInLen, void *pUser)
    {
        if (ENUM_DEV_ON == dwDataType)
        {
           NET_EHOME_DEV_REG_INFO *pDevInfo = (NET_EHOME_DEV_REG_INFO *)pOutBuffer;
     
           if (pDevInfo != NULL)
           {
              lLoginID = lUserID;
              printf("On-line, lUserID: %d, Device ID: %s
    ", lLoginID, pDevInfo->byDeviceID);
           }
           //输入参数
           NET_EHOME_SERVER_INFO *pServerInfo = (NET_EHOME_SERVER_INFO *)pInBuffer;
           pServerInfo->dwTimeOutCount = 6; //心跳超时次数
           pServerInfo->dwKeepAliveSec = 15; //心跳间隔
        }
        else if (ENUM_DEV_OFF == dwDataType)
        {
    	printf("Off-line, lUserID: %d
    ", lUserID);
    	NET_ECMS_ForceLogout(lUserID);       
        }
        else
        {
        }
     
        return TRUE;
    }
     
    //
    //处理文件流数据
    BOOL InputStreamData(BYTE byDataType, char* pBuffer, int iDataLen)
    {	
        if(Videofile == NULL)
        {
            Videofile = fopen("Test.mp4","wb");
            printf("Save data to file: Test.mp4!");
        }
     
        if(Videofile!= NULL)
        {
            fwrite(pBuffer,iDataLen,1,Videofile);  //下载视频文件
        }
     
        //调用播放库解码并显示码流实现回放
        /* 
        if(1 == byDataType)
        {
            if (!PlayM4_GetPort(&m_lPort))
            {
                return FALSE;
            }
            if (!PlayM4_SetStreamOpenMode(m_lPort, STREAME_REALTIME))
            {
                return FALSE;
            }
            //Enter first 40-byte header
            if(!PlayM4_OpenStream(m_lPort, (unsigned char *)pBuffer, (DWORD)iDataLen, 2*1024*1024))
            {
                return FALSE; 
            }
            if(!PlayM4_Play(m_lPort, hWnd))
            {
                return FALSE;
            }
        }
        else
        {	
            for (int i=0; i<1000; i++)
            {
                BOOL bRet = PlayM4_InputData(m_lPort,(unsigned char *)pBuffer, (DWORD)iDataLen);
                if (!bRet)
                {
                    if ( i >=999)
                    {
                        printf("PlayM4_InputData failed, error code: %d!", PlayM4_GetLastError(m_lPort));
                    }	
                    Sleep(2);
                }
            }
        }
        */
        return TRUE;
    }
     
    //
    //注册回放码流回调函数
    BOOL CALLBACK fnPLAYBACK_DATA_CB(LONG lPlayBackLinkHandle, NET_EHOME_PLAYBACK_DATA_CB_INFO *pDataCBInfo, void *pUserData)
    {
        if (NULL == pDataCBInfo)
        {
            return FALSE;
        }
        lPlayHandle = lPlayBackLinkHandle;
        InputStreamData(pDataCBInfo->dwType, (char*)pDataCBInfo->pData, pDataCBInfo->dwDataLen);
        return TRUE;
    }
     
    //
    //注册回访请求的响应回调函数
    BOOL CALLBACK fnPLAYBACK_NEWLINK_CB(LONG lPlayBackLinkHandle, NET_EHOME_PLAYBACK_NEWLINK_CB_INFO  *pNewLinkCBMsg, void *pUserData)
    {
        lLinkHandle = lPlayBackLinkHandle;
        printf("Callback of playback listening, Device ID: %s
    ", pNewLinkCBMsg->szDeviceID);
     
        //回放数据的回调参数
        NET_EHOME_PLAYBACK_DATA_CB_PARAM struDataCB = {0};
        struDataCB.fnPlayBackDataCB = fnPLAYBACK_DATA_CB;
        struDataCB.byStreamFormat = 0;//封装格式:0-PS格式
     
        if (!NET_ESTREAM_SetPlayBackDataCB(lPlayBackLinkHandle, &struDataCB))
        {
            printf("NET_ESTREAM_SetPlayBackDataCB failed, error code: %d
    ", NET_ESTREAM_GetLastError());
            return FALSE;
        }
        printf("NET_ESTREAM_SetPlayBackDataCB!
    ");
     
        return TRUE;
    }
     
    /
    //设置异常回调
    NET_ESTREAM_SetExceptionCallBack(0, 0, StreamExceptionCallback, NULL);
     
    void CALLBACK StreamExceptionCallback(DWORD dwType, LONG iUserID, LONG iHandle, void* pUser)
    {
        if(EHOME_PREVIEW_EXCEPTION == dwType)
        {
    	    //预览异常
            printf("Preview exception, handle=%d, Error:%d", iHandle, dwError);
        }
        else if (EHOME_PLAYBACK_EXCEPTION == dwType)
        {
    	    //回放异常
            printf("Playback exception, handle=%d, Error:%d", iHandle, dwError);
        }
        else if (EHOME_AUDIOTALK_EXCEPTION == dwType)
        {
    	    //语音对讲(转发)异常
            printf("Stream VoiceTalk exception, handle=%d, Error:%d", iHandle, dwError);
        }
    } 
     
    void main(){
        
        //SMS在开启监听服务后获取码流
     
        //初始化SMS库
        NET_ESTREAM_Init();
     
        //回放的监听参数
        NET_EHOME_PLAYBACK_LISTEN_PARAM struListen = {0};
        memcpy(struListen.struIPAdress.szIP,"10.16.2.123", sizeof("10.16.2.123"));
        struListen.struIPAdress.wPort = 8003; //SMS的监听端口号
        struListen.fnNewLinkCB = fnPLAYBACK_NEWLINK_CB; //回放请求的回调函数
        struListen.pUserData = NULL;
        struListen.byLinkMode = 0; //0-TCP, 1-UDP(保留)
     
        //开启监听服务
        LONG lHandle = NET_ESTREAM_StartListenPlayBack(&struListen);
        if(lHandle < -1)
        {
            printf("NET_ESTREAM_StartListenPlayBack failed, error code: %d
    ", NET_ESTREAM_GetLastError());
            NET_ESTREAM_Fini();
            return;
        }
        printf("NET_ESTREAM_StartListenPlayBack!
    ");
        //
     
        
        //注册和回放请求
     
        //初始化CMS库
        NET_ECMS_Init();
     
        //注册的监听参数
        NET_EHOME_CMS_LISTEN_PARAM struCMSListenPara = {0};
        memcpy(struCMSListenPara.struAddress.szIP, "0.0.0.0", sizeof("0.0.0.0"));
        struCMSListenPara.struAddress.wPort = 7660;
        struCMSListenPara.fnCB = RegisterCallBack;
     
        //开启监听服务并接收设备注册信息
        LONG lListen = NET_ECMS_StartListen(&struCMSListenPara);
        if(lListen < -1)
        {
            printf("NET_ECMS_StartListen failed, error code: %d
    ", NET_ECMS_GetLastError());
            NET_ECMS_Fini();
            return;
        }
        printf("NET_ECMS_StartListen!
    ");
     
        while(1)
        {
            Sleep(1000);  //以下操作需在注册完成后再进行
            if(lLoginID >= 0)
            {
                break;
            }
        }
     
        //查找视频文件
        NET_EHOME_REC_FILE_COND struFindCond = {0};
        struFindCond.dwChannel =1;  //通道号,从1开始
        struFindCond.dwRecType = 0xff; //所有类型
        struFindCond.dwStartIndex = 0;  //查找起始位置
        struFindCond.dwMaxFileCountPer = 5;  //单次搜索的最多文件数量
     
        //查找开始时间
        struFindCond.struStartTime.wYear = (WORD)2015;
        struFindCond.struStartTime.byMonth = (BYTE)5;
        struFindCond.struStartTime.byDay = (BYTE)18;
        struFindCond.struStartTime.byHour = (BYTE)10;
        struFindCond.struStartTime.byMinute = (BYTE)0;
        struFindCond.struStartTime.bySecond = (BYTE)0;
     
        //查找结束时间
        struFindCond.struStopTime.wYear = (WORD)2015;
        struFindCond.struStopTime.byMonth = (BYTE)5;
        struFindCond.struStopTime.byDay = (BYTE)18;
        struFindCond.struStopTime.byHour = (BYTE)12;
        struFindCond.struStopTime.byMinute = (BYTE)59;
        struFindCond.struStopTime.bySecond = (BYTE)59;
     
        LONG lSearchType = 0; //查找文件
        LONG lFileHandle = NET_ECMS_StartFindFile_V11(lLoginID, lSearchType, &struFindCond, sizeof(struFindCond)); //Start file search
        if (lFileHandle < 0)
        {		 
            printf("NET_ECMS_StartFindFile_V11 failed, error code: %d
    ", NET_ECMS_GetLastError());
            NET_ECMS_Fini();
            return;
        }
        printf("NET_ECMS_StartFindFile_V11!
    ");
     
        LONG lRet = -1;
        char csTmp[256] = {0};	
        char szFileName[MAX_FILE_NAME_LEN] = {0};
     
        NET_EHOME_REC_FILE struFileInfo = {0};
     
        //可在线程中搜索文件
        while(1)
        {
            lRet = NET_ECMS_FindNextFile_V11(lFileHandle, &struFileInfo, sizeof(struFileInfo));//逐个获取搜索结果
            if (lRet == ENUM_GET_NEXT_STATUS_SUCCESS)
            {
                if (struFileInfo.dwFileSize / 1024 == 0)
                {
                    sprintf(csTmp,"%d",struFileInfo.dwFileSize);
                }
                else if (struFileInfo.dwFileSize / 1024 > 0 && struFileInfo.dwFileSize /(1024*1024) == 0)
                {
                    sprintf(csTmp,"%dK",struFileInfo.dwFileSize/1024);
                }
                else
                {
                    sprintf(csTmp,"%dM",struFileInfo.dwFileSize /1024/1024);
                }
     
                printf("Filename[%s], Filesize[%s], StarTime[%04d-%02d-%02d %02d:%02d:%02d], StopTime[%04d-%02d-%02d %02d:%02d:%02d] 
    ", 
                    struFileInfo.szFileName, csTmp, struFileInfo.struStartTime.wYear, struFileInfo.struStartTime.byMonth, 
                    struFileInfo.struStartTime.byDay, struFileInfo.struStartTime.byHour, struFileInfo.struStartTime.byMinute,
                    struFileInfo.struStartTime.bySecond, struFileInfo.struStopTime.byDay, struFileInfo.struStopTime.byHour, 
                    struFileInfo.struStopTime.byMinute, struFileInfo.struStopTime.bySecond);//Searched file information
     
                memcpy(szFileName, struFileInfo.sFileName, MAX_FILE_NAME_LEN);
            }
            else
            {
                if (lRet == ENUM_GET_NETX_STATUS_NEED_WAIT)
                {
                    Sleep(5);
                    continue;
                }
     
                if ((lRet == ENUM_GET_NETX_STATUS_NO_FILE) || (lRet == ENUM_GET_NEXT_STATUS_FINISH))
                {
                    printf("No more file!
    ");
                    break;
                }
                else if(lRet == ENUM_GET_NEXT_STATUS_NOT_SUPPORT)
                {
                    printf("Device does not support!
    ");
                    break;
                }
                else
                {
                    printf("Failed to find a file, for the server is busy or network failure!
    ");
                    break;
                }
            }
        }
     
        //回放请求的输入参数 
        NET_EHOME_PLAYBACK_INFO_IN struPlayBackIn = {0};
        struPlayBackIn.dwSize = sizeof(struPlayBackIn);
        struPlayBackIn.dwChannel = 1; //通道号
        struPlayBackIn.byPlayBackMode = 0; //回放模式:0-按文件名回放,1-按时间回放(保留)
        struPlayBackIn.unionPlayBackMode.struPlayBackbyName.dwSeekType = 0; //0-按字节长度计算,1-按秒数计算
        struPlayBackIn.unionPlayBackMode.struPlayBackbyName.dwFileOffset = 0; 
        //当dwSeekType为0时,偏移量按字节计算;当dwSeekType等于1时,偏移量按秒数计算
        struPlayBackIn.unionPlayBackMode.struPlayBackbyName.dwFileSpan = 0; //已下载的文件大小,如果大小为0,说明文件已下载完成
        memcpy(struPlayBackIn.unionPlayBackMode.struPlayBackbyName.szFileName, szFileName, MAX_FILE_NAME_LEN);//需要进行回放的文件名称
     
        memcpy(struPlayBackIn.struStreamSever.szIP, "10.16.2.123", sizeof("10.16.2.123")); //SMS的IP地址
        struPlayBackIn.struStreamSever.wPort = 8003; //SMS的端口号,需和监听端口号一致
     
        //回放请求的输出参数
        NET_EHOME_PLAYBACK_INFO_OUT struPlayBackOut = {0};
     
        //回放请求
        if(!NET_ECMS_StartPlayBack(lLoginID, &struPlayBackIn, &struPlayBackOut))
        {
            printf("NET_ECMS_StartPlayBack failed, error code: %d
    ", NET_ECMS_GetLastError());
            NET_ECMS_Fini();
            return;
        }
        printf("NET_ECMS_StartPlayBack!
    ");
     
        //码流传输请求的输入参数
        NET_EHOME_PUSHPLAYBACK_IN struPushPlayBackIn = {0};
        struPushPlayBackIn.dwSize = sizeof(struPushPlayBackIn);
        struPushPlayBackIn.lSessionID = struPlayBackOut.lSessionID; //回放请求的会话ID
     
        //码流传输请求的输出参数
        NET_EHOME_PUSHPLAYBACK_OUT struPushPlayBackOut = {0};
     
        //发送请求给设备并开始传输码流
        if(!NET_ECMS_StartPushPlayBack(lLoginID, &struPushPlayBackIn, &struPushPlayBackOut))
        {
            printf("NET_ECMS_StartPushPlayBack failed, error code: %d
    ", NET_ECMS_GetLastError());
            NET_ECMS_Fini();
            return;
        }
        printf("NET_ECMS_StartPushPlayBack!
    ");
     
        Sleep(50000);
     
        
        //登出
     
        //CMS停止监听服务
        if(!NET_ECMS_StopListen(lListen))
        {
            printf("NET_ECMS_StopListen failed, error code: %d
    ", NET_ECMS_GetLastError());
        }
     
        //释放被CMS占用的资源
        NET_ECMS_Fini();
        //
     
        //SMS停止转发码流
        if(lPlayHandle >= 0)
        {
    		if (!NET_ESTREAM_StopPlayBack(lPlayHandle))
            {
                printf("NET_ESTREAM_StopPlayBack failed, error code: %d
    ", NET_ECMS_GetLastError());
            }
        }
     
        //SMS停止监听服务
        if(lLinkHandle >= 0)
        {
            if (!NET_ESTREAM_StopListenPlayBack(lLinkHandle))
            {
                printf("NET_ESTREAM_StopListenPlayBack failed, error code: %d
    ", NET_ECMS_GetLastError());
            }
        }
        //释放被SMS占用的资源
        NET_ESTREAM_Fini();
     
        //释放文件资源
        if(Videofile != NULL)
        {
            fclose(Videofile);
            Videofile = NULL;
        }
     
        printf("Exit!
    ");
    }
    

      

     
  • 相关阅读:
    现在实习生做什么好找工作?
    MSsql数据库修改数据类型Float到decimal的问题处理
    首记,一种新的企业信息化平台开发方案——AgileEAS.NET框架
    在Winform中使用DataGirdView时的添加和删除操作
    如何通过AgileEAS.NET快速搭建属于你的企业应用(一)——解决方案的建立
    浅谈企业自主信息化开发模式
    AgileEAS开发中关于实体类和DataTable的取舍——用linq+orm来缩短你的开发周期
    如何通过AgileEAS.NET快速搭建属于你的企业应用(二)——智能版本升级和多数据库访问的分布式部署
    整站黑白页
    布局管理器
  • 原文地址:https://www.cnblogs.com/EasyNVR/p/13607150.html
Copyright © 2011-2022 走看看