unity gb28181 rtsp 视频孪生图像拉流和矫正插件(一)

2023-09-18 22:47:53

目的是为了视频孪生,将视频放到三维里面,如果使用自己写的插件,有更好的灵活性,同时断线重连等等都更好控制了。

1、矫正算法和硬件解码

最好使用opencv制作,可以使用opencv的cuda加速,opencv的编译,必须用cuda cudnn, 都装好,再编译。硬件解码写在插件里面。
在这里插入图片描述
dll插件使用extern “C” 方式。使用_declspec(dllexport) 将函数输出。

2、gb28181 和 rtsp 流 插件

如果多线程?不要在插件里面使用多线程,插件里面保证简单,只是函数,使用unity c# 的多线程启动多个线程去拉流。尽量将插件做到简单的函数封装,不要封装过多的操作。gb28181 使用网络接收推流的方式接收数据,demux使用c++ 解封装,在插件里面解码。

2.1、rtsp 断线重连

还是使用ffmpeg制作,包含断线重连功能,这个必须有,生成unity的可执行程序的时候,一旦rtsp 链接断掉,就必须使用断线重连。否则unity 播放的部分就白了。

2.2、gb28181 接收

这个使用sip协议和流媒体协议,网内尽量使用udp,简单,单个线程接收所有输送的流, 接收到数据以后分流,unity中在update 函数里面去拉自己想要的流。

2.3 多路

界面

在这里插入图片描述
拉好场景,使用两个plane,每一个plane使用一个rtsp或者gb28181 链接,同时序列化结构体,使得c++和c# 能够使用结构体进行参数传递。


using System;
using System.Text;
using System.Threading;
using System.Collections;
using UnityEngine;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public struct FRAME
{
    public int width;
    public int height;
    public int len;
    public IntPtr Frame ;
    public IntPtr data;
    //public byte[] data;
    //[MarshalAs(UnmanagedType.LPArray)]
}
[StructLayout(LayoutKind.Sequential)]
public struct PARAM
{
    public double p1;
    public double p2;
    public double p3;
    public double p4;
    public double p5;
    public double p6;
    public double p7;
    public double p8;
    public double p9;
    public double c1;
    public double c2;
    public double c3;
    public double c4;
    public double c5;
}

接口定义

 [DllImport("rtspPlugin")]
 public static extern bool rtsp_test([MarshalAs(UnmanagedType.LPStr)] string url);

 [DllImport("rtspPlugin")]
 public static extern bool rtsp_test_data([MarshalAs(UnmanagedType.LPStr)] string url, 
     [MarshalAs(UnmanagedType.LPArray)] byte[] data, ref FRAME frame);

 [DllImport("rtspPlugin")]
 public static extern void rtsp_test_stop([MarshalAs(UnmanagedType.LPStr)] string url);

 [DllImport("rtspPlugin")]
 public static extern void rtsp_test_setparam([MarshalAs(UnmanagedType.LPStr)] string url,ref PARAM param);

程序启动,界面上来两个控制按钮,开始线程和结束线程。
在这里插入图片描述
程序启动的时候启动两个按钮,一个使用矫正,一个不使用矫正,下图所示,左边的流已经经过矫正,图像被拉直,右图没有,以示区别。

在这里插入图片描述
增加一点三维的气氛
在这里插入图片描述
播放
在这里插入图片描述
视频贴图过程
由于使用了硬件解码,解码出来的是nv12格式,如果使用ffmpeg 的swscale,函数缩放和变成rgb24是可以的,效率不高, 也可以直接贴图nv12格式。

Texture2D tY = null,
Texture2D tU = null;
void trans_show(ref struct param)
{
 private Texture2D tY, tU;
 int w = param->width;
 int h = param->height;
 if(tY == null)
 {
 	tY = new Texture2D(w, h, TextureFormat.Alpha8, false);
 	tU = new Texture2D(w/2, h/2, TextureFormat.RG16, false);
 }
}

//在update里显示,y 和 uv 分别是 avframe 里面的y 数据指针和uv数据指针
tY.LoadRawTextureData(y);
tY.Apply();
            
 tU.LoadRawTextureData(uv);
 tU.Apply();
 
 rawImage.texture = tY;
 rawImage.material.SetTexture("_UTex", tU);

着色器代码显示

sampler2D _YTex;
sampler2D _UTex;
fixed4 frag (v2f i) : SV_Target
{
         fixed4  col;
         float  y = tex2D(_YTex, i.uv).a;
         fixed4  uvs = tex2D(_UTex, i.uv);
         float  u = uvs.r - 0.5;
         float  v = uvs.g - 0.5;
          float r = y + 1.403 * v;
          float g = y - 0.344  * u - 0.714 * v;
          float b = y + 1.770  * u;
          col.rgba = float4(r, g, b, 1.0f);
           return col;
}

不用shader 转换nv12

不用shader,使用cuda 直接转可以试试一下cuda函数

__global__ void YCrCb2RGBConver(uchar *pYdata, uchar *pUVdata,int stepY, int stepUV, uchar *pImgData, int width, int height, int channels)
{
    const int tidx = blockIdx.x * blockDim.x + threadIdx.x;
    const int tidy = blockIdx.y * blockDim.y + threadIdx.y;

    if (tidx < width && tidy < height)
    {
        int indexY, indexU, indexV;
        uchar Y, U, V;
        indexY = tidy * stepY + tidx;    
        Y = pYdata[indexY];

        if (tidx % 2 == 0)
        {
            indexU = tidy / 2 * stepUV + tidx;
            indexV = tidy / 2 * stepUV + tidx + 1;
            U = pUVdata[indexU];
            V = pUVdata[indexV];
        }
        else if (tidx % 2 == 1)
        {
            indexV = tidy / 2 * stepUV + tidx;
            indexU = tidy / 2 * stepUV + tidx - 1;
            U = pUVdata[indexU];
            V = pUVdata[indexV];
        }

        pImgData[(tidy*width + tidx) * channels + 2] = uchar (Y + 1.402 * (V - 128));
        pImgData[(tidy*width + tidx) * channels + 1] = uchar (Y - 0.34413 * (U - 128) - 0.71414*(V - 128));
        pImgData[(tidy*width + tidx) * channels + 0] = uchar (Y + 1.772*(U - 128));
    }
}
更多推荐

王道考研计算机组成原理

王道考研计算机组成原理计算机系统概述计算机系统层次结构计算机的性能指标错题数据的表示和运算数制与编码运算方法和运算电路浮点数的表示与运算存储系统存储器概述主存储器主存储器与CPU的连接外部存储器高速缓冲存储器虚拟存储器指令系统指令格式指令的寻址方式程序的机器级代码表示CISC和RISC的基本概念中央处理器CPU的功能和

苹果专用解压缩推荐 BetterZip 5 中文for mac

BetterZip5是一款功能强大的解压缩软件,旨在帮助用户在Mac上快速、方便地解压缩各种压缩文件格式。它支持常见的压缩文件格式,如ZIP、RAR、7z、TAR、GZIP等,并提供了一系列高级功能和工具。以下是BetterZip5解压缩的一般步骤:打开BetterZip5:在Mac上启动BetterZip5应用程序。

TCP拥塞控制,拥塞窗口,携带应答,捎带应答,面向字节流,异常情况处理,最终完结弹

之前我们已经将TCP的前面一些性质介绍过了,接下来来介绍剩余的一些性质1.确认应答2.超时重新传输3.连接管理4.滑动窗口5.流量控制目录一、拥塞控制二、拥塞窗口三、携带应答四、粘包问题方法1:应用层协议引入分隔符方法2:应用层协议引入包长度五、TCP异常情况的处理一、拥塞控制💛总的传输效率,是一个木桶效应,取决于最

[JAVAee]SpringBoot配置文件

配置文件的介绍配置文件当中记录了许多重要的配置信息,例如:数据库的连接信息(用户的账户与密码)项目的启动端口第三方系统的调用密匙用于记录问题产生的日志在spring框架中一些特定的框架会自动调用配置文件中的配置信息来运用.配置文件中的属性也起到了类似全局变量的作用.对于一个项目,可以准备多种配置文件方便自由调用来应对不

tdesign的文件上传(微信小程序+idea的springboot)

目录1.springboot后端1.1FileController.java1.2listener文件的ErpApplicationListener.java1.3【重点!】FileServiceImpl层1.4IFileService1.5StringUtil通用类1.6主程序加一个监听器1.7application

Spring学习笔记1 启示录

写段代码,引出Spring的好处创建个空工程,然后在工程里建模块可能是IEAD版本问题,每次建新的空工程,都需要退出重进设置下maven和Encoding新建模块持久层接口持久层实现类业务层接口业务层实现类控制层(表现层)建个测试类测试分析这个程序存在的问题假设现在新需求是因某种原因需要改变Dao层的实现类并且在业务层

Feign远程调用丢失请求头

前言我们在写服务端项目的时候,总会限制对某些资源的访问,最常见的就是要求用户先登录才能访问资源,当用户登录后就会将此次会话信息保存进session,同时返回给浏览器指定的cookie键值,下次浏览器再次访问,请求头中就会携带这个cookie,我们也以次来识别用户的登录状态,做出正确响应。一、问题有时候,我们先行登录,然

什么是 Spring Boot Starter?(InsCode AI 创作助手)

当你开始使用SpringBoot开发应用程序时,你可能会听说过SpringBootStarter,它是SpringBoot框架的一个关键概念。本篇博客将详细介绍SpringBootStarter是什么,为什么它如此重要,以及如何使用它来简化SpringBoot项目的依赖管理。什么是SpringBootStarter?S

CG Magic分享同一场景里下,VR渲染器和CR渲染器哪个好?

渲染操作时,VR渲染器和CR渲染器的对比成为常见问题了。这个问题很多人都会问。今天CGMagic小编通过一个真实的项目,就是同一场景下来比较一下VR渲染器和CR渲染器的区别。以下图为例是用来测试的场景当年的最终图。采用了当年的一个伊丽莎白大街152号的项目场景,来做一下测试。1、用VR渲染,大小为2K,这张图耗时75分

(21)多线程实例应用:双色球(6红+1蓝)

一、需求1.双色球:投注号码由6个红色球号码和1个蓝色球号码组成。2.红色球号码从01--33中选择,红色球不能重复。3.蓝色球号码从01--16中选择。4.最终结果7个号码:6+1;即33选6(红)+16选1(蓝)5.产品:能用;用户放心使用;原则:靠运气,不能有暗箱操作,号码开奖的随机性。6.做法思路:(1)从左往

短视频矩阵源码系统

一、什么是短视频矩阵源码?短视频矩阵源码是一种基于短视频平台的软件程序,它可以帮助用户在多个短视频平台上进行短视频营销。短视频矩阵源码包含了多种功能,例如短视频上传、短视频批量管理、短视频数据分析等等。用户可以根据自己的需求,选择不同的功能来实现短视频营销的目标。二、短视频矩阵源码的优势是什么?节省时间和人力成本:短视

热文推荐