QT5.6 MSVC编译器 实现-海康摄像头,获取H.264裸码流并通过libmp4V2实现MP4写封装生成MP4视频文件

前言

当前,在国内安防领域,海康摄像头一直是受各个解决方案比较青睐的摄像头选择。本项目主要应用海康摄像头对桥梁道路车辆运行情况进行监控。当桥梁称重系统检测到车辆异常信号后,触发摄像服务程序,采集摄像头在该时间段内的是视频数据(事件的前五秒与后五秒)并保存为MP4文件,上传至FTP服务供后期使用。

视频知识补充

在这里插入图片描述
海康摄像头获取回放视频文件通常为H.264编码格式,rtp,ps,ts封装协议的视频文件,安放领域较长使用的视频封装协议。而web页面只支持MP4封装协议的文件播放。所以本方案采用获取裸码流,并使用libmp4V2的方法进行MP4协议封装

关键代码

海康裸码获取

static void CALLBACK PlayBackH264DataCallBack(LONG lPlayHandle, NET_DVR_PACKET_INFO_EX *struPackInfo, void *pUser)
{
    StructH264Process *obj = static_cast<StructH264Process *>(pUser);
    switch (struPackInfo->dwPacketType)
    {

    case FILE_HEAD:     // 头
        break;

    case VIDEO_I_FRAME: // I 帧
        obj->MP4.getConvertMP4File(struPackInfo->pPacketBuffer, struPackInfo->dwPacketSize, struPackInfo->dwPacketType);
        break;

    case VIDEO_B_FRAME: // B 帧
        break;

    case VIDEO_P_FRAME: // P 帧
        obj->MP4.getConvertMP4File(struPackInfo->pPacketBuffer, struPackInfo->dwPacketSize, struPackInfo->dwPacketType);
        break;

    default:       // 其他数据
        break;
    }
}

CHKProcess::CHKProcess(QObject *parent) : QObject(parent)
{
}

int CHKProcess::init(QString host, int port, QString usr, QString pwd)
{
     //---------------------------------------
     // 初始化
     NET_DVR_Init();
     //设置连接时间与重连时间
     NET_DVR_SetConnectTime(2000, 1);
     NET_DVR_SetReconnect(10000, true);

     //---------------------------------------
     // 注册设备
     //登录参数,包括设备地址、登录用户、密码等
     NET_DVR_USER_LOGIN_INFO struLoginInfo = {0};
     struLoginInfo.bUseAsynLogin = 0; //同步登录方式
     strcpy(struLoginInfo.sDeviceAddress, host.toStdString().data()); //设备IP地址
     struLoginInfo.wPort = port; //设备服务端口
     strcpy(struLoginInfo.sUserName, usr.toStdString().data()); //设备登录用户名
     strcpy(struLoginInfo.sPassword, pwd.toStdString().data()); //设备登录密码

     //设备信息, 输出参数
     NET_DVR_DEVICEINFO_V40 struDeviceInfoV40 = {0};

     m_userId = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40);
     if (m_userId< 0)
     {
         qDebug()<<"HIKVISION login fail,last error"<<NET_DVR_GetLastError();
         NET_DVR_Cleanup();
         return -1;
     }
     qDebug()<<"HIKVISION connect!";
     return 0;
}

void CHKProcess::downLoadFile(uint64_t startTime, uint64_t endTime,QString enventId,QString did)
{
    p_H264Process.isfinish = false;
    p_H264Process.isok = false;
    QString fileName = QCoreApplication::applicationDirPath()+"/cache/V_"+enventId+"_"+did+".mp4";
    if(!p_H264Process.MP4.CreateMP4File(fileName.toStdString()))
    {
        qDebug()<<"Failed to create MP4 file";
        p_H264Process.isfinish = true;
        p_H264Process.isok = false;
        p_H264Process.MP4.getMP4FileClose();
        p_H264Process.MP4.init();
        return;
    }

    uint64_t currentTime = QDateTime::currentDateTime().toTime_t();
    if((startTime>endTime) || (startTime>currentTime))
    {
        qDebug()<<"startTime:Command time parameter error";
        p_H264Process.isfinish = true;
        p_H264Process.isok = false;
        p_H264Process.MP4.getMP4FileClose();
        p_H264Process.MP4.init();
        return;
    }

    if(currentTime<endTime)
    {
        if(endTime - currentTime>100)
        {
             qDebug()<<"Error:The end time is more than 100 seconds ahead of the current time";
             p_H264Process.isfinish = true;
             p_H264Process.isok = false;
             p_H264Process.MP4.getMP4FileClose();
             p_H264Process.MP4.init();
             return;
        }
        QThread::sleep(endTime-currentTime);
    }
    QString strStartTime = QDateTime::fromTime_t(startTime).toString("yyyyMMddhhmmss");
    QString strEndTime = QDateTime::fromTime_t(endTime).toString("yyyyMMddhhmmss");
    QDate startDate = QDate::fromString(strStartTime.mid(0,8),"yyyyMMdd");
    QDate endDate = QDate::fromString(strEndTime.mid(0,8),"yyyyMMdd");

    QTime qstartTime = QTime::fromString(strStartTime.mid(8,6),"hhmmss");
    QTime qendTime = QTime::fromString(strEndTime.mid(8,6),"hhmmss");


    //按时间回放
    NET_DVR_VOD_PARA struVodPara = { 0 };
    struVodPara.dwSize = sizeof(struVodPara);
    struVodPara.struIDInfo.dwSize = sizeof(NET_DVR_STREAM_INFO);
    struVodPara.struIDInfo.dwChannel = 1;
    struVodPara.hWnd = NULL;

    struVodPara.struBeginTime.dwYear = startDate.year();
    struVodPara.struBeginTime.dwMonth = startDate.month();
    struVodPara.struBeginTime.dwDay = startDate.day();
    struVodPara.struBeginTime.dwHour = qstartTime.hour();
    struVodPara.struBeginTime.dwMinute = qstartTime.minute();
    struVodPara.struBeginTime.dwSecond = qstartTime.second();
    struVodPara.struEndTime.dwYear = endDate.year();
    struVodPara.struEndTime.dwMonth = endDate.month();
    struVodPara.struEndTime.dwDay = endDate.day();
    struVodPara.struEndTime.dwHour = qendTime.hour();
    struVodPara.struEndTime.dwMinute = qendTime.minute();
    struVodPara.struEndTime.dwSecond = qendTime.second();

    //---------------------------------------
    //按时间回放
    p_H264Process.hPlayback = NET_DVR_PlayBackByTime_V40(m_userId, &struVodPara);
    if(p_H264Process.hPlayback < 0)
    {
        printf("NET_DVR_PlayBackByTime_V40 fail,last error %d\n", NET_DVR_GetLastError());
        p_H264Process.isfinish = true;
        p_H264Process.isok = false;
        p_H264Process.MP4.getMP4FileClose();
        p_H264Process.MP4.init();
        return;
    }
    //---------------------------------------
    //开始
    if (!NET_DVR_PlayBackControl_V40(p_H264Process.hPlayback, NET_DVR_PLAYSTART, NULL, 0, NULL, NULL))
    {
        printf("HK play back control start failed [%d]\n", NET_DVR_GetLastError());
        p_H264Process.isfinish = true;
        p_H264Process.isok = false;
        p_H264Process.MP4.getMP4FileClose();
        p_H264Process.MP4.init();
        return;
    }

    NET_DVR_SetPlayBackESCallBack(p_H264Process.hPlayback,PlayBackH264DataCallBack,&p_H264Process);

    QThread::sleep(10); //10s延迟用于等待视频流数据返回

    if(!NET_DVR_StopPlayBack(p_H264Process.hPlayback))
    {
        printf("HK failed to stop play back [%d]\n",NET_DVR_GetLastError());
        p_H264Process.isfinish = true;
        p_H264Process.isok = false;
        p_H264Process.MP4.getMP4FileClose();
        p_H264Process.MP4.init();
        return;
    }
    p_H264Process.MP4.getMP4FileClose();
    p_H264Process.MP4.init();
    p_H264Process.isok = true;
    p_H264Process.isfinish = true;
    qDebug()<<"HK"<<" Video download complete %100";
    qDebug()<<"*";


    //---------------------------------------
    //设置文件封装格式
    int p = 4;
    if(!NET_DVR_PlayBackControl_V40(hPlayback,NET_DVR_SET_TRANS_TYPE,&p,4,NULL,NULL))
    {
        qDebug()<<"HK Play setting failed,last error "<<NET_DVR_GetLastError();
        p_isok = false;
        return;
    }

    //开始下载
     if(!NET_DVR_PlayBackControl_V40(hPlayback, NET_DVR_PLAYSTART, NULL, 0, NULL,NULL))
    {
        qDebug()<<"HK Play back control failed,last error "<<NET_DVR_GetLastError();
        p_isok = false;
        return;
    }

    int nPos = 0;
    for(nPos = 0; nPos < 100&&nPos>=0; nPos = NET_DVR_GetDownloadPos(hPlayback))
    {
        QThread::msleep(500);
    }
    if(!NET_DVR_StopGetFile(hPlayback))
    {
        printf("HK failed to stop get file [%d]\n",NET_DVR_GetLastError());
        p_isok = false;
        return;
    }
    if(nPos<0||nPos>100)
    {
        qDebug()<<"HK download err,last error "<<NET_DVR_GetLastError();
        QFile file(fileName);
        if(file.open(QIODevice::ReadOnly))
        {
            if(file.size() == 0)
            {
                p_isok = false;
                qDebug()<<"Video download fail,not upload ftp!";
                return;
            }
        }
    }
    p_isok = true;
    qDebug()<<"HK"<<QString("V_")+enventId+"_"+did+".mp4"<<" Video download complete %"<<nPos<<"\n";
    qDebug()<<"*";
}

CHKProcess::~CHKProcess()
{
    //注销用户
    NET_DVR_Logout(m_userId);
    //释放SDK资源
    NET_DVR_Cleanup();
}
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值