福州大学《嵌入式系统综合设计》实验十三:RTSP拉流与RTMP推流

 一、实验目的

掌握基于算能平台的JPEG压缩编码方法以及开发环境,包括开发主机环境搭建,硬件嵌入式开发板的连接,云平台的配置,编码程序的编译、运行等。

二、实验内容

搭建实验开发环境,并编写静止图像jpeg格式编解码程序,输入端读取原始图像数据,选择编解码模式,输出压缩编码结果。在目标开发机运行测试,验证开发环境。如果是基于云平台虚拟环境,则需要将编译好的程序代码上传云平台进行测试运行。

三、开发环境

开发主机:Ubuntu 20.04.6 LTS

硬件:算能SE5

四、实验器材

开发主机 + 云平台(或SE5硬件)

五、实验过程与结果

参考例程

本实验可以参考git上的ocv_video_xcode.cpp例程完成。

实验内容与步骤

图1 连接部署图

如上图所示,本实验利用OpenCV接口,在SE5上实现通过RTSP拉流,然后通过RTMP将码流推送给PC/服务器。在实现过程中,RTSP拉流和RTMP推流分别在不同的线程中实现。并且,RTSP拉流的过程中会进行解码,在RTMP推流的过程中会进行编码操作。

本实验中的摄像头也可以直接通过PC机一起完成,可以在PC机上安装并启动RTSP Server。

推荐使用EasyDarwin安装RTSP Server:https://www.easydarwin.org/

也可以直接在SE5上安装,则需要下载源码并进行编译后在SE5上进行安装。PC上可以安装Nginx作为RTMP服务器。

Windows下Nginx服务器的安装和RTMP服务器开启方法见附件描述。

本实验两个线程的操作流程如下图:

在上述处理流程中,在主线程中只需要将open的文件名设置为RTSP地址即可实现对视频流的拉取,然后将读取后的视频帧(解码后的视频帧)存入视频缓存队列,在写线程中将write的文件名设置为RTMP即可实现将视频流推送到指定地址。

在OpenCV中分别提供了VideoCapture类和VideoWriter类用于视频文件的读和写操作。下面介绍具体的编程实现过程。

主线程函数

OpenCV获取视频流

如前所述,OpenCV通过VideoCapture类实现对URL地址进行读取,并进行解码。这部分相关的代码也可以参考实例11来实现,其关键代码如下:

//初始化VideoCapture类
VideoCapture cap;
//打开文件或者摄像头或者某个RTSP连接
cap.open(threadPara->inputUrl, CAP_FFMPEG, threadPara->deviceId);
...
//读取视频帧存入image中
Mat image;
cap.read(image); 

代码中的threadPara->inputUrl即为输入的RTSP视频流地址。threadPara->deviceId为板卡ID,如果是SOC模式,则为0,如果是PCIE模式需要指定具体的板卡ID。

 视频帧存入视频缓存队列

主线程通过cap.read(image)获取到image后,存入视频缓存队列。本实验中涉及两个不同的线程对缓存队列进行读写操作,为保障线程同步,需要通过上锁和解锁对缓存队列进行保护:

g_video_lock.lock();
//存入缓存队列
threadPara->imageQueue->push(image);
g_video_lock.unlock();

上述代码中获取到的MAT格式的image就是解码后的视频帧数据。

写线程函数

OpenCV推送视频流

OpenCV提供了写入视频的接口类VideoWriter,VideoWriter是向文件中以指定的编码格式将每一帧图片写入到视频中。可以直接通过VideoWriter类对URL地址进行推流:

VideoWriter  writer;       //创建VideoWriter类  
//outfile输出视频文件的路径名称
//fourcc: 字符类型的编码,表示用于编码视频文件的编码器,比如采用HEVC编码
writer.open(outfile, VideoWriter::fourcc('h', 'v', 'c', '1'),
        threadPara->fps,             //帧率
        Size(threadPara->imageCols, threadPara->imageRows),
        encodeparms,
        true,
        threadPara->deviceId);
writer.write(*toEncImage); //通过write接口推送

fourcc接口还可以设置不同的编码方式比如:

VideoWriter::fourcc('P','I','M','1') //表示MPEG-1 编码文件扩展名为avi; VideoWriter::fourcc('X','V','I','D') //表示MPEG-4编码文件扩展名为avi; VideoWriter::fourcc('X','2','6','4') //表示MPEG-4编码文件扩展名为mp4;
VideoWriter::fourcc('I','4','2','0') //表示YUV编码,文件扩展名为avi;
VideoWriter::fourcc('M','P','4','V') //表示旧的MPEG-4编码,文件扩展名为avi;
VideoWriter::fourcc('T','H','E','O') //表示使用ogg vorbis,文件扩展名为ogv;
VideoWriter::fourcc('F','L','V','1') //表示flash video,文件扩展名为flv;

本实验中的RTSP服务器端可以直接通过摄像头进行拉流,也可以通过在PC机上安装RTSP服务器来完成。本实验中的RTMP服务器可以通过安装Nginx服务器来完成。安装Nginx的流程如下:

Windows下Nginx服务器的安装与RTMP使用

Nginx官网:nginx news  ,然后点击“download”

  

选择最新版本或稳定版本

  

 解压Nginx,进入CMD,进到目录后并运行start nginx或者ngnix.exe。

进入conf文件夹,打开nginx.conf文件,增加配置如下:

worker_processes  1;

events {
    worker_connections  1024;
}

rtmp {
    server {
        listen 1935;
        chunk_size 4000;
        application live {
             live on;
             allow publish 127.0.0.1;
             allow play all;
        }
    }
}

配置HTTP

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
 
    server {
        listen       80;
        server_name  localhost;
        
        #location / {
        #   root   html;
        #    index  index.html index.htm;
        #}
        
        # Serve HLS fragments
        location /hls {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
        root /tmp;
            add_header Cache-Control no-cache;
        }

        # Serve DASH fragments
        location /dash {
            root /tmp;
            add_header Cache-Control no-cache;
        }
 
        location /live_hls {
            types{
                #m3u8 type设置
                application/vnd.apple.mpegurl m3u8;
                #ts分片文件设置
                video/mp2t ts;
            }
            #指向访问m3u8文件目录
            alias ./m3u8File;
                add_header Cache-Control no-cache; #禁止缓存
        }
        
        location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }
        location /stat.xsl{
            root ./nginx-rtmp-module;
        }
 
        location /control {
            rtmp_control all;
        }
 
        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

 验证nginx配置文件

cd nginx所在目录
nginx -t

启动nginx

cd nginx所在目录
start nginx
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

验证nginx

在浏览器输入:http://localhost/,查看nginx是否启动 

在浏览器输入:http://localhost/stat,查看媒体流服务的情况

VLC拉流

安装VLC播放器,并打开软件。

左上角媒体→打开网络串流→网络,配置URL(格式形如:rtmp://ip:port/live)

rtmp://127.0.0.1:1935/live

点击播放,验证是否成功拉到了流。

Wireshark安装与使用

Wireshark下载安装

下载地址:Wireshark · Go Deep

根据自己的操作系统选择对应的版本:

打开Wireshark,并选择监听的网卡

也可以选择:

然后选择自己对应的网卡:

进入抓包

设置过滤

ip.addr == 192.0.2.1   //设置仅捕获IP地址为192.0.2.1的报文 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/203242.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

visionOS空间计算实战开发教程Day 10 照片墙

本例选择了《天空之城》的25张照片,组成5x5的照片墙)。首先我们在setupContentEntity方法中构建了一个纹理数组,将这25张照片添加到数组images中。其中封装了setup方法,借助于visionOS对沉浸式空间的支持,我们创建了三…

vuepress-----4、侧边栏

# 4、侧边栏 # 自动生成侧栏 如果你希望自动生成一个仅仅包含了当前页面标题(headers)链接的侧边栏,你可以通过 YAML front matter 来实现: --- sidebar: auto ---你也可以通过配置来在所有页面中启用它: // .vuep…

网络调试助手 连接Onenet 多协议接入平台 TCP透传协议

onenet文档链接 多协议接入地址 打开Onenet平台,多协议接入 选择TCP透传协议,点击添加产品,输入信息,点击确认 点击设备列表,添加设备 下面需要上传一个解析脚本文件该文件的下载地址lua文件下载地址 建立连接 设备…

入门指南:Vue的安装配置和开发环境设置

背景: ​ 这里想讲一讲为什么使用框架,而不使用原生的HTML、CSS、JavaScript写。原生开发虽然灵活,但在大型项目中可能导致代码重复、维护困难等问题,不符合软件工程的"高内聚低耦合"原则。例如,如果每个页…

盘点68个Android系统源码安卓爱好者不容错过

盘点68个Android系统源码安卓爱好者不容错过 学习知识费力气,收集整理更不易。 知识付费甚欢喜,为咱码农谋福利。 源码下载链接:https://pan.baidu.com/s/1FcBxCe7KpJsh0zFxNZ_7wg?pwd8888 提取码:8888 项目名称 Android …

python基础练习题库实验7

文章目录 题目1代码实验结果题目2代码实验结果题目3代码实验结果题目总结题目1 编写代码创建一个名为Staff的类和方法__init__,以按顺序初始化以下实例属性: -staff_number -first_name -last_name -email 代码 class Staff:def __init__(self, staff_number, first_name,…

第三方检测机构实验室信息管理系统LIMS全套源码

​LIMS实验室信息管理系统源码,支持二次开发 LIMS实验室信息管理系统是一种软件类型,旨在通过跟踪与样品、实验、实验室工作流程和仪器相关的数据,提高实验室产能和效率。覆盖实验室从合同审批、委托下单、样品管理、生产调度、检测记录、报告…

CDA level-2 备考经验分享 转数据分析师CDA证书备考 考试相关说明

抓住了23年的尾巴,正好给我考过了CDA level-2 ,虽然今年只有这几个小收获,但是还是很开心了,毕竟知足常乐嘛。 由于工作原因,因此复习都是间断性的,勉勉强强给通过了,只得了个C。 考试注册报名与…

贪心算法的介绍

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解&#…

VMD-Attention-LSTM 价格预测实战

VMD-Attention-LSTM时间序列价格预测实战 完整数据代码可直接运行_哔哩哔哩_bilibili 数据展示:数据有几万条 足够的 主要模型代码: import tensorflow as tfdef attention_3d_block(inputs,TIME_STEPS,SINGLE_ATTENTION_VECTOR):# inputs.shape = (batch_size, time_steps,…

如何使用 CSS columns 布局来实现自动分组布局?

最近在项目中碰到这样一个布局,有一个列表,先按照 4 2 的正常顺序排列,当超过 8 个后,会横向重新开始 4 2 的布局,有点像一个个独立的分组,然后水平排列,如下 图中序号是 dom 序列,所…

循环神经网络RNN

1. 背景 RNN(Recurrent Neural Networks) CNN利用输入中的空间几何结构信息;RNN利用输入数据的序列化特性。 2. SimpleRNN单元 传统多层感知机网络假设所有的输入数据之间相互独立,但这对于序列化数据是不成立的。RNN单元用隐藏状态或记忆引入这种依赖…

人工智能原理复习--知识表示(二)

文章目录 上一篇产生式表示法推理方式 结构化表示语义网络语义网络表示知识的方法和步骤应用题目 框架表示法下一篇 上一篇 人工智能原理复习–知识表示(一) 产生式表示法 把推理和行为的过程用产生式规则表示,所以又称基于规则的系统。 产…

两台电脑如何快速传输几百G文件,这款文件传输软件真快

当我们需要传输数百GB的文件时,使用传统工具对于大型文件传输来说往往效率低下。这些方法可能需要数小时,甚至数天才能完成传输。然而,现代生活和工作中,我们经常需要以更快速、更高效的方式传输大文件,无论是因为工作…

聚观早报 |亚马逊AWS发布新AI芯片;拼多多Q3营收增长94%

【聚观365】11月30日消息 亚马逊AWS发布新AI芯片 拼多多Q3营收增长94% Redmi K70全新国风配色揭晓 英伟达扩大自动驾驶中国团队 华为nova 12参数细节曝光 亚马逊AWS发布新AI芯片 在美国时间周二举办的Reinvent大会上,亚马逊旗下的云计算部门AWS发布了新的人工…

Flutter App混淆加固、保护与优化原理

​ 引言 在移动应用程序开发中,保护应用程序的代码和数据安全至关重要。本文将探讨如何对Flutter应用程序进行混淆、优化和保护,以提高应用程序的安全性和隐私。 一、混淆原理 混淆是一种代码保护技术,通过修改源代码或编译后的代码&#…

2.Ansible的copy模块,我最常用的模块

1. 简述 先从我自身的情况来说,我不是运维人员,并且对linux操作也不是特别熟悉,所以工作中我使用ansible基本就是在平常的自动化部署中,而使用最多的模块就是copy模块。我使用copy模块也主要是来替换生产环境的配置文件。所以&am…

无醇啤酒行业分析:预计2028年将达到106亿美元

按照国际惯用的标准划分,通常将酒精度3.5%-4%的称为普通啤酒,将酒精度大于0.5%、小于2.5%的称为低醇啤酒,而酒精度小于0.5%便称为无醇啤酒。酒精给人带来的兴奋感,与体育比赛的紧张刺激相辅相成,啤酒也成为了许多球迷们…

OBC、DCDC自动化测试解决方案!

OBC(车载充电机)和DCDC(直流-直流变换器)是电动汽车的核心部件,DCDC和OBC的功能质量对于整车的性能和安全性至关重要。在OBC和DCDC,以及整车开发测试过程中,需要对OBC和DCDC进行功能和性能方面进行全面的测…

C陷阱与缺陷——第3章 语义陷阱

1. 指针和数组 C语言中只有一维数组,而且数组的大小必须在编译器就作为一个常数确定下来,然而在C语言中数组的元素可以是任何类型的对象,当然也可以是另外的一个数组,这样,要仿真出一个多维数组就不是难事。 对于一个…