由于公司做了一个展馆项目,甲方要在程序内接入监控视频,而且是接入600个,果断没有头绪,好在ue4给出了官方实列,再开几个线程就 le.废话不多说直接上代码。

先把OpenCV的插件接上去,接其他应用SDK下篇文章介绍。
在Actor使用的方法.
如果使用主线程解析视频的话,进程启动会卡一段时间,一个监控有时候就会卡顿半分钟,六个会更卡,所以果断开了六个线程.
    UFUNCTION(BlueprintCallable, Category = Webcam)
        void OpenWebCamera(TArray< FString> urlAr);

UFUNCTION(BlueprintCallable, Category = Webcam)
        void OpenLocalCamera(TArray< int32> ID);

UFUNCTION(BlueprintCallable, Category = Webcam)
        void CloseCamera();

TArray< RSTDataHandle*>Camer1RSTDataHandleArr;
    TArray<FRunnableThread*> m_RecvThreadArr;
    
    virtual void BeginDestroy()override;
//根据RSTP连接的数量创建线程
gamezaivoid ACamReader::OpenWebCamera(TArray< FString> urlAr)
{
    for (int32 i = 0; i < 6; i++)
    {
        RSTDataHandle*tempSTDataHandle = new RSTDataHandle();
        Camer1RSTDataHandleArr.Add(tempSTDataHandle);
        FRunnableThread *tempRunnableThread = FRunnableThread::Create(new FReceiveThread(tempSTDataHandle, urlAr[i]), TEXT("RecvThread"), 128 * 1024, TPri_AboveNormal, FPlatformAffinity::GetPoolThreadMask());
        m_RecvThreadArr.Add(tempRunnableThread);
    }
}

void ACamReader::OpenLocalCamera(TArray< int32> IDArr)
{
    if (Camer1RSTDataHandleArr.Num() > 0)
    {
        for (int32 i = 0; i < Camer1RSTDataHandleArr.Num(); i++)
        {
            Camer1RSTDataHandleArr[i]->OpenLocalCamera(IDArr[i]);
        }
    }
}

void ACamReader::CloseCamera()
{
    if (Camer1RSTDataHandleArr.Num() > 0)
    {
        for (int32 i = 0; i < Camer1RSTDataHandleArr.Num(); i++)
        {
            Camer1RSTDataHandleArr[i]->CloseCamera();
        }
    }
//
}

//获取取得的视频图片
UTexture2D* ACamReader::GetTexture2D(int Index)
{
    if (Camer1RSTDataHandleArr.Num() > 0)
    {
        for (int32 i = 0; i < Camer1RSTDataHandleArr.Num(); i++)
        {
            if (Index==i)
            {
                if (Camer1RSTDataHandleArr[i]->GetThisUTexture2D())
                {
                    return Camer1RSTDataHandleArr[i]->GetThisUTexture2D();
                }
            }
        }
    }
    return nullptr;
}

TArray<UTexture2D*> ACamReader::GetAllTexture2D()
{
    if (Camer1RSTDataHandleArr.Num() > 0)
    {
        for (int32 i = 0; i < Camer1RSTDataHandleArr.Num(); i++)
        {
            if (Camer1RSTDataHandleArr[i]->GetThisUTexture2D())
            {
                CurrenTextureArr.Add(Camer1RSTDataHandleArr[i]->GetThisUTexture2D());
            }    
        }
    }
    return CurrenTextureArr;
}

void AWebcamReader::InitStream()
{
    if (Camer1RSTDataHandleArr.Num() > 0)
    {
        for (int32 i = 0; i < Camer1RSTDataHandleArr.Num(); i++)
        {
            Camer1RSTDataHandleArr[i]->InitStream();
        }
    }
}
//这个地方在Editor里面运行会有随机崩溃,最好用宏定义在debuggame下测试,这里用的是老代码就不占了.
void AWebcamReader::BeginDestroy()
{
    Super::BeginDestroy();
    if (Camer1RSTDataHandleArr.Num() > 0)
    {
        for (int32 i = 0; i < Camer1RSTDataHandleArr.Num(); i++)
        {
            delete Camer1RSTDataHandleArr[i];
            Camer1RSTDataHandleArr[i] = nullptr;
        }
    }
    Camer1RSTDataHandleArr.Reset();
    if (m_RecvThreadArr.Num() > 0)
    {
        for (int32 i = 0; i < m_RecvThreadArr.Num(); i++)
        {
            m_RecvThreadArr[i]->Kill(true);
            delete m_RecvThreadArr[i];
            m_RecvThreadArr[i] = nullptr;

}
    }
    m_RecvThreadArr.Reset();
}
4.下面看一下在线程里干了什么事.

//构造一个数据类
FReceiveThread::FReceiveThread(RSTDataHandle *sTDataHandle, FString url):STDataHandle(sTDataHandle),URL(url)
{

}

FReceiveThread::~FReceiveThread()
{
    stopping = true;
    delete STDataHandle;
    STDataHandle = nullptr;
}

bool FReceiveThread::Init()
{
    stopping = false;
    return true;
}
//更新数据
uint32 FReceiveThread::Run()
{
    
    STDataHandle->OpenWebCamera(URL);
    //接收数据包
    while (!stopping)   //线程计数器控制
    {

STDataHandle->Tick(0.01f);
                //Sleep一下吧,要不然占用CPU过高,
        FPlatformProcess::Sleep(0.01f);    
    }

return 1;
}
5.线程里干的事很简单吧,下面看一下数据类里面的数据怎么处理的.

E数据// Fill out your copyright notice in the Description page of Project Settings.

#include "RSTDataHandle.h"

RSTDataHandle::RSTDataHandle()
{
    VideoTexture = nullptr;
    CameraID = 0;
    isStreamOpen = false;
    VideoSize = FVector2D(0, 0);
    ShouldResize = false;
    ResizeDeminsions = FVector2D(320, 240);
    stream = cv::VideoCapture();
    frame = cv::Mat();
    Mutex = new FCriticalSection();
}

RSTDataHandle::~RSTDataHandle()
{
}

//够简单吧,就干这么多事,其他的数据都是UE官方插件做好的,你只负责调用即可.
void RSTDataHandle::Tick(float DeltaTime)
{    
        UpdateFrame();
        DoProcessing();
        UpdateTexture();
        OnNextVideoFrame();    
}

void RSTDataHandle::OnNextVideoFrame()
{

}

void RSTDataHandle::UpdateFrame()
{
    if (stream.isOpened())
    {
        stream.read(frame);
        if (ShouldResize)
        {
            cv::resize(frame, frame, size);
        }
    }
    else {
        isStreamOpen = false;
    }
}

void RSTDataHandle::DoProcessing()
{

}

void RSTDataHandle::UpdateTexture()
{
    if (isStreamOpen && frame.data)
    {
        // Copy Mat data to Data array
        for (int y = 0; y < VideoSize.Y; y++)
        {
            for (int x = 0; x < VideoSize.X; x++)
            {
                int i = x + (y * VideoSize.X);
                Data[i].B = frame.data[i * 3 + 0];
                Data[i].G = frame.data[i * 3 + 1];
                Data[i].R = frame.data[i * 3 + 2];
            }
        }

// Update texture 2D
        UpdateTextureRegions(VideoTexture, (int32)0, (uint32)1, VideoUpdateTextureRegion, (uint32)(4 * VideoSize.X), (uint32)4, (uint8*)Data.GetData(), false);
    }
}

void RSTDataHandle::OpenWebCamera(FString url)
{
    stream = cv::VideoCapture(TCHAR2STRING(url.GetCharArray().GetData()));
    if (stream.isOpened())
    {
        InitStream();
        UE_LOG(LogTemp, Warning, TEXT("stream.OpenSucess"));
    }
    else
    {
        OpenWebCamera(url);
        UE_LOG(LogTemp, Warning, TEXT("stream.isOpened()"));
    }
}

void RSTDataHandle::OpenLocalCamera(int32 ID)
{
    CameraID = ID;
    stream.open(CameraID);
    InitStream();
}

void RSTDataHandle::CloseCamera()
{
    if (stream.isOpened()) {
        stream.release();
    }
}

UTexture2D* RSTDataHandle::GetThisUTexture2D()
{
    FScopeLock ScopeLock(Mutex);
    return VideoTexture;
}

void RSTDataHandle::InitStream()
{
    if (stream.isOpened() && !isStreamOpen)
    {
        // Initialize stream
        isStreamOpen = true;
        UpdateFrame();
        VideoSize = FVector2D(frame.cols, frame.rows);
        size = cv::Size(ResizeDeminsions.X, ResizeDeminsions.Y);
        VideoTexture = UTexture2D::CreateTransient(VideoSize.X, VideoSize.Y);
        VideoTexture->UpdateResource();
        VideoUpdateTextureRegion = new FUpdateTextureRegion2D(0, 0, 0, 0, VideoSize.X, VideoSize.Y);

// Initialize data array
        Data.Init(FColor(0, 0, 0, 255), VideoSize.X * VideoSize.Y);

// Do first frame
        DoProcessing();
        UpdateTexture();
        OnNextVideoFrame();
    }
}

void RSTDataHandle::UpdateTextureRegions(UTexture2D* Texture, int32 MipIndex, uint32 NumRegions, FUpdateTextureRegion2D* Regions, uint32 SrcPitch, uint32 SrcBpp, uint8* SrcData, bool bFreeData)
{
    if (Texture->Resource)
    {
        struct FUpdateTextureRegionsData
        {
            FTexture2DResource* Texture2DResource;
            int32 MipIndex;
            uint32 NumRegions;
            FUpdateTextureRegion2D* Regions;
            uint32 SrcPitch;
            uint32 SrcBpp;
            uint8* SrcData;
        };

FUpdateTextureRegionsData* RegionData = new FUpdateTextureRegionsData;

RegionData->Texture2DResource = (FTexture2DResource*)Texture->Resource;
        RegionData->MipIndex = MipIndex;
        RegionData->NumRegions = NumRegions;
        RegionData->Regions = Regions;
        RegionData->SrcPitch = SrcPitch;
        RegionData->SrcBpp = SrcBpp;
        RegionData->SrcData = SrcData;

ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
            UpdateTextureRegionsData,
            FUpdateTextureRegionsData*, RegionData, RegionData,
            bool, bFreeData, bFreeData,
            {
            for (uint32 RegionIndex = 0; RegionIndex < RegionData->NumRegions; ++RegionIndex)
            {
                int32 CurrentFirstMip = RegionData->Texture2DResource->GetCurrentFirstMip();
                if (RegionData->MipIndex >= CurrentFirstMip)
                {
                    RHIUpdateTexture2D(
                        RegionData->Texture2DResource->GetTexture2DRHI(),
                        RegionData->MipIndex - CurrentFirstMip,
                        RegionData->Regions[RegionIndex],
                        RegionData->SrcPitch,
                        RegionData->SrcData
                        + RegionData->Regions[RegionIndex].SrcY * RegionData->SrcPitch
                        + RegionData->Regions[RegionIndex].SrcX * RegionData->SrcBpp
                        );
                }
            }
            if (bFreeData)
            {
                FMemory::Free(RegionData->Regions);
                FMemory::Free(RegionData->SrcData);
            }
            delete RegionData;
            });
    }

}
6.接监控也并不难吧,只是里面的细节比较多.这里就不上监控的图细聊了.

7.还有如果监控那边设置的分辨率过高,用的是主码, ,码率过高,的话接多个监控CPU直接100,电脑会很卡的.当时测试一个监控,后来测试6个,电脑卡的直接要关机了,以为自己的代码有问题,纠结了很久才知道是监控设置的问题.如果不要求视频是高清的,同时接六个一点都不比VLC效果差,还有一个坑,一个监控可能会有5路或者六路的限制.

视频监控和ue4结合相关推荐

  1. 深度学习-智能视频监控

    深度学习-智能视频监控 Deep Surveillance with Deep Learning – Intelligent Video Surveillance 原文地址: https://data ...

  2. 视频监控系统供电方式及选择方法

    目录 1.独立供电模式 2.集中供电模式 3.POE供电模式 3.1.交换机和终端都支持POE 3.2.交换机支持POE,终端不支持POE 3.3.交换机不支持POE,终端支持POE 3.4.交换机和 ...

  3. 10 ping不通widwos7 windwos_弱电老司机总结的10种视频监控系统故障解决方法,学会,事半功倍...

    最近有许多的读者咨询关于视频监控系统维修方法的事情,有没有总结一些常见故障的解决方案呢?当然有的,今天分享一些常见故障解决方法. 正文: 视频监控系统通常出现摄像机没有画面.或者画面卡顿.丢失等情况, ...

  4. C# 视频监控系列(9):服务器端——数据捕获(抓图 + 录像)

    前言 录像功能是监控系统中最重要的功能之一,除了本文的功能实现外,还需要你自己考虑合适的存储策略:存储大小.时间段.存储盘符等. 注意 本系列文章限于学习交流,注重过程,由于涉及公司,所以不提供源代码 ...

  5. 华为云家庭视频监控帮你一起守护家

    设想一下? 离开家了突然想起家里空调没关怎么办? 家里没人有陌生人入侵了怎么办? 不在家家里老人出事了怎么办? 不用愁,总有办法解决的,这些日常生活中极容易遇到的事情,没有分身术的时候,华为云家庭视频 ...

  6. 怎样的视频监控的管理与运营才算高效

    去年5月份,国家发布<关于加强公共安全视频监控建设联网应用工作的若干意见>,针对新形势下维护国家和社会稳定,预防和打击暴力恐怖犯罪,提升城乡管理水平与创新社会治理体制提出了新的要求. 视频 ...

  7. C# 视频监控系列(2):客户端——封装API

    前言 本章主要是在C#封装的海康DVR客户端SDK 的代码上修改的,并参考<Hikvision 板卡网络开发包编程手册V4.7.pdf>补上更完整的注释,并且参照VC++源码做了小部分修改 ...

  8. 2021综述:视频监控中的多目标跟踪

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 来源丨CV技术指南 作者丨仿佛若有光 前言 本文来自一篇2021的论文,论文简要回顾了现有的SOTA模 ...

  9. 移动4G打造排污视频监控系统助力咸宁环保建设

    针对排污企业分布零散.监管部门无法实时掌握和发现企业污染情况和环境安全隐患等问题,咸宁市环保局联合咸宁移动,在重点排污企业安装视频监控系统,利用高速.稳定的移动4G网络,实现排污情况24小时实时监控. ...

最新文章

  1. 谈谈HTML5中的history.pushSate方法,弥补ajax导致浏览器前进后退无效的问题
  2. B站面试官炫耀身价过亿,贬低北邮应试者引热议!不知北邮毕业的B站创始人作何感想?
  3. [云炬创业基础笔记]第六章商业模式测试23
  4. ubuntu swift mysql_使用 Swift 3.0 操作 MySQL 数据库
  5. python接口自动化测试三:代码发送HTTP请求
  6. [渝粤教育] 广东-国家-开放大学 21秋期末考试Java程序设计基础10232k2
  7. 微服务架构和SOA的区别
  8. 语言差异引起的问题解决一例
  9. linux防火墙配置管理,Linux之Iptables防火墙管理与配置 -电脑资料
  10. python 心电处理包_python 黏包现象及其解决方案
  11. 全球最大地标识别数据集问世:包含200万张图片和3万处地标
  12. linux系统q7文件,linux系统安装包的管理
  13. 全局唯一序号生成方案
  14. HTML5前端开发之基础篇
  15. 单目深度估计综述(updating...)
  16. 道长运维之CPU负载高
  17. Latex 排版命令总结
  18. 如何学习有限元分析 有限元分析学习心得
  19. 快速实现B站(B ili b ili)手机缓存m4s文件转mp4(批量升级版)
  20. Vue入门(安装配置启动项目)

热门文章

  1. 麓言信息UI设计和平面设计有什么区别?
  2. PCB电路设计规范细节
  3. MySQL之prepare用法
  4. 求某一年的某一月有多少天
  5. 欧盟调查显示100Mbps宽带网络建设需5020亿欧元资金
  6. microsoft vbscript编译器错误怎么解决_Win10电脑遇到DistributedCOM错误10016怎么解决?「系统天地」...
  7. 30岁的男人学些啥技术好些?
  8. ECSHOP 数据库结构说明 (适用版本v2.7.3)
  9. 拿来即用——报表画图(饼图,速率图,表格图,柱状图)
  10. OSS Browser的使用