ffmpeg RTP PS推流
要实现 CRtpSendPs 类,使其能够将 H264 数据通过 RTP PS 流推送到指定的 URL,并支持 TCP 和 UDP 传输方式,您需要使用 FFmpeg 库。以下是该类的实现示例,包括必要的初始化、推流和退出函数。
步骤
- 初始化 FFmpeg 库:需要初始化 FFmpeg 网络、格式和编码器相关的库。
- 配置 RTP 传输:使用 RTP 封装 PS (Program Stream) 格式。
- 推送数据:接收 H264 数据并将其封装为 RTP 包,发送到指定的目标 URL(支持 UDP 和 TCP)。
- 退出处理:释放相关资源。
完整代码实现
#include <iostream>
#include <string>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
#include <libavdevice/avdevice.h>
#include <libavfilter/avfilter.h>
#include <libswscale/swscale.h>class CRtpSendPs
{
public:CRtpSendPs();~CRtpSendPs();int Init(const char *url, bool bUdpOrTcp); // 初始化,设置目标 URL 和传输协议int PushStream(const void *pH264Data, uint32_t u32Len); // 推送视频数据int Exit(); // 清理资源private:AVFormatContext *outputFmtCtx;AVStream *outputStream;AVCodecContext *codecCtx;AVPacket pkt;bool isUdp;std::string outputUrl;bool isInitialized;
};CRtpSendPs::CRtpSendPs() : outputFmtCtx(nullptr), outputStream(nullptr), codecCtx(nullptr), isInitialized(false)
{av_register_all();avformat_network_init();avcodec_register_all();avdevice_register_all();isUdp = true;isInitialized = false;
}CRtpSendPs::~CRtpSendPs()
{Exit();
}int CRtpSendPs::Init(const char *url, bool bUdpOrTcp)
{if (isInitialized) {std::cerr << "Already initialized!" << std::endl;return -1;}isUdp = bUdpOrTcp;outputUrl = url;// Create output contextAVOutputFormat *fmt = av_guess_format(NULL, outputUrl.c_str(), NULL);if (!fmt) {std::cerr << "Could not guess output format!" << std::endl;return -1;}int ret = avformat_alloc_output_context2(&outputFmtCtx, fmt, NULL, outputUrl.c_str());if (ret < 0) {std::cerr << "Failed to create output context!" << std::endl;return ret;}// Create a new stream for the outputoutputStream = avformat_new_stream(outputFmtCtx, NULL);if (!outputStream) {std::cerr << "Failed to create new stream!" << std::endl;return AVERROR(ENOMEM);}// Setup codec parameters (for H264)AVCodec *encoder = avcodec_find_encoder(AV_CODEC_ID_H264);if (!encoder) {std::cerr << "H264 encoder not found!" << std::endl;return AVERROR_ENCODER_NOT_FOUND;}codecCtx = avcodec_alloc_context3(encoder);if (!codecCtx) {std::cerr << "Failed to allocate codec context!" << std::endl;return AVERROR(ENOMEM);}codecCtx->codec_id = AV_CODEC_ID_H264;codecCtx->bit_rate = 1000000;codecCtx->width = 1920;codecCtx->height = 1080;codecCtx->time_base = {1, 30}; // 30 fpscodecCtx->gop_size = 12;codecCtx->max_b_frames = 3;codecCtx->pix_fmt = AV_PIX_FMT_YUV420P;ret = avcodec_open2(codecCtx, encoder, NULL);if (ret < 0) {std::cerr << "Failed to open codec!" << std::endl;return ret;}// Copy codec parameters to the streamret = avcodec_parameters_from_context(outputStream->codecpar, codecCtx);if (ret < 0) {std::cerr << "Failed to copy codec parameters!" << std::endl;return ret;}// Open the output file or network streamif (!(outputFmtCtx->oformat->flags & AVFMT_NOFILE)) {ret = avio_open(&outputFmtCtx->pb, outputUrl.c_str(), AVIO_FLAG_WRITE);if (ret < 0) {std::cerr << "Failed to open output URL!" << std::endl;return ret;}}// Write the header of the file (or stream)ret = avformat_write_header(outputFmtCtx, NULL);if (ret < 0) {std::cerr << "Failed to write header!" << std::endl;return ret;}isInitialized = true;return 0;
}int CRtpSendPs::PushStream(const void *pH264Data, uint32_t u32Len)
{if (!isInitialized) {std::cerr << "Not initialized!" << std::endl;return -1;}// Create a packet and fill it with H264 dataav_init_packet(&pkt);pkt.data = (uint8_t *)pH264Data;pkt.size = u32Len;pkt.stream_index = outputStream->index;pkt.flags |= AV_PKT_FLAG_KEY; // Assuming it's a keyframe, adjust if needed// Write the packet to the RTP streamint ret = av_write_frame(outputFmtCtx, &pkt);if (ret < 0) {std::cerr << "Error writing frame!" << std::endl;return ret;}return 0;
}int CRtpSendPs::Exit()
{if (!isInitialized) {return 0; // Already exited}av_write_trailer(outputFmtCtx);// Close the output stream and free resourcesif (outputFmtCtx && !(outputFmtCtx->oformat->flags & AVFMT_NOFILE)) {avio_closep(&outputFmtCtx->pb);}avcodec_free_context(&codecCtx);avformat_free_context(outputFmtCtx);isInitialized = false;return 0;
}
代码说明
-
CRtpSendPs 类的构造函数和析构函数:
Init():初始化 FFmpeg 输出格式和编码器配置,设置输出 URL 并建立连接。PushStream():接受一帧 H264 数据并将其封装为 RTP 包,然后通过网络发送。Exit():释放资源并关闭输出流。
-
FFmpeg 配置:
- 使用
avformat_alloc_output_context2()创建输出流上下文。 - 使用
avcodec_find_encoder()查找 H264 编码器,初始化编码器上下文。 - 使用
av_write_frame()将数据包发送到指定的输出 URL(支持 RTP 协议)。
- 使用
-
RTP 传输:通过 RTP 推送数据流,支持 UDP 和 TCP(通过 URL 中的协议部分决定)。
编译命令
在编译前,确保已经安装了 FFmpeg 库。如果没有安装,您可以使用以下命令:
sudo apt-get install libavformat-dev libavcodec-dev libavutil-dev libavdevice-dev libswscale-dev
然后使用以下命令来编译代码:
g++ -o rtp_send_ps rtp_send_ps.cpp -lavformat -lavcodec -lavutil -lavdevice -lswscale -lavfilter -lm -lz
运行示例
./rtp_send_ps rtp://192.168.0.49:5000
此命令将会把 H264 数据通过 RTP 协议推送到目标 IP 地址 192.168.0.49,端口 5000。
注意事项
- 您需要确保目标服务器或设备能够接收 RTP 流。
- 在真实应用中,
PushStream()中的 H264 数据可以从文件或网络中获取,并通过该函数传输。
相关文章:
ffmpeg RTP PS推流
要实现 CRtpSendPs 类,使其能够将 H264 数据通过 RTP PS 流推送到指定的 URL,并支持 TCP 和 UDP 传输方式,您需要使用 FFmpeg 库。以下是该类的实现示例,包括必要的初始化、推流和退出函数。 步骤 初始化 FFmpeg 库:…...
Rust语言俄罗斯方块(漂亮的界面案例+详细的代码解说+完美运行)
tetris-demo A Tetris example written in Rust using Piston in under 500 lines of code 项目地址: https://gitcode.com/gh_mirrors/te/tetris-demo 项目介绍 "Tetris Example in Rust, v2" 是一个用Rust语言编写的俄罗斯方块游戏示例。这个项目不仅是一个简单…...
NUMA架构及在极速网络IO场景下的优化实践
NUMA技术原理 NUMA架构概述 随着多核CPU的普及,传统的对称多处理器(SMP)架构逐渐暴露出性能瓶颈。为了应对这一问题,非一致性内存访问(NUMA, Non-Uniform Memory Access)架构应运而生。NUMA架构是一种内存…...
Brain.js 用于浏览器的 GPU 加速神经网络
Brain.js 是一个强大的 JavaScript 库,它允许开发者在浏览器和 Node.js 环境中构建和训练神经网络 。这个库的目的是简化机器学习模型的集成过程,使得即使是没有深厚机器学习背景的开发者也能快速上手 。 概述 Brain.js 提供了易于使用的 APIÿ…...
Linux——用户级缓存区及模拟实现fopen、fweite、fclose
linux基础io重定向-CSDN博客 文章目录 目录 文章目录 什么是缓冲区 为什么要有缓冲区 二、编写自己的fopen、fwrite、fclose 1.引入函数 2、引入FILE 3.模拟封装 1、fopen 2、fwrite 3、fclose 4、fflush 总结 前言 用快递站讲述缓冲区 收件区(类比输…...
视觉感知与处理:解密计算机视觉的未来
文章目录 前言1. 计算机视觉的概述2. 计算机视觉的应用3. 运动感知与光流4. 人类视觉感知4.1 大脑中的视觉处理4.2 视觉缺陷与对比4.3 分辨率4.4 视觉错觉5. 图像采集与处理6. 图像处理流程7. 二值图像处理与分割8. 3D 机器视觉系统8.1 主动3D视觉8.2 立体视觉9. 商业机器视觉系…...
【大数据学习 | Spark-Core】广播变量和累加器
1. 共享变量 Spark两种共享变量:广播变量(broadcast variable)与累加器(accumulator)。 累加器用来对信息进行聚合,相当于mapreduce中的counter;而广播变量用来高效分发较大的对象,…...
postgresql按照年月日统计历史数据
1.按照日 SELECT a.time,COALESCE(b.counts,0) as counts from ( SELECT to_char ( b, YYYY-MM-DD ) AS time FROM generate_series ( to_timestamp ( 2024-06-01, YYYY-MM-DD hh24:mi:ss ), to_timestamp ( 2024-06-30, YYYY-MM-DD hh24:mi:ss ), 1 days ) AS b GROUP BY tim…...
pywin32库 -- 读取word文档中的图形
文章目录 前置操作解析body中的图形解析页眉中的图形 前置操作 基于pywin32打开、关闭word应用程序; import pythoncom from win32com.client import Dispatch, GetActiveObjectdef get_word_instance():""" 获取word进程 实例"""py…...
GitLab使用示例
以下是从 新建分支开始,配置 GitLab CI/CD 的完整详细流程,涵盖每个步骤、配置文件路径和具体示例。 1. 新建分支并克隆项目 1.1 在 GitLab 上创建新分支 登录 GitLab,进入目标项目页面。依次点击 Repository > Branches。点击右上角 Ne…...
uniapp echarts tooltip formation 不识别html
需求: echarts 的tooltip 的域名太长,导致超出屏幕 想要让他换行 思路一: 用formation自定义样式实现换行 但是: uniapp 生成微信小程序, echart种的tooltip 的formation 识别不了html ,自定义样式没办…...
3D扫描对文博行业有哪些影响?
三维扫描技术对文博行业产生了深远的影响,主要体现在以下几个方面: 一、高精度建模与数字化保护 三维扫描技术通过高精度扫描设备,能够捕捉到文物的每一个细节,包括形状、纹理、颜色等,从而生成逼真的3D模型。这些模…...
面试(十一)
目录 一.IO多路复用 二.为什么有IO多路复用机制? 三.IO多路复用的三种实现方式 3.1 select select 函数接口 select 使用示例 select 缺点 3.2 poll poll函数接口 poll使用示例 poll缺点 3.3 epoll epoll函数接口 epoll使用示例 epoll缺点 四. 进程和线程的区别…...
React-useState的使用
useState 是 React 提供的一个 Hook,允许你在函数组件中添加和管理状态(state)。在类组件中,状态管理通常是通过 this.state 和 this.setState 来实现的,而在函数组件中,useState 提供了类似的功能。 基本…...
设计模式之破环单例模式和阻止破坏
目录 1. 序列化和反序列化2. 反射 这里单例模式就不多说了 23种设计模式之单例模式 1. 序列化和反序列化 这里用饿汉式来做例子 LazySingleton import java.io.Serializable;public class LazySingleton implements Serializable {private static LazySingleton lazySinglet…...
11.19c++面向对象+单例模式
编写如下类: class File{ FILE* fp }; 1:构造函数,打开一个指定的文件 2:write函数 向文件中写入数据 3:read函数,从文件中读取数据,以string类型返回 代码实现: #include <iostream>using namespace std;class…...
一文了解TensorFlow是什么
TensorFlow是一个开源的机器学习框架,由Google开发并维护。它提供了一个灵活且高效的环境,用于构建和训练各种机器学习模型。 TensorFlow的基本概念包括: 张量(Tensor):TensorFlow中的核心数据结构&#x…...
如何做好一份技术文档?
打造出色技术文档的艺术 在当今技术驱动的世界中,技术文档扮演着至关重要的角色。它不仅是工程师和开发人员之间交流的桥梁,更是产品和技术成功的隐形推手。一份优秀的技术文档宛如一张精准的航海图,能够引导读者穿越技术的迷雾,…...
Linux和Ubuntu的关系
Linux和Ubuntu的关系: 1. Linux本身是内核,Ubuntu系统是基于Linux内核的操作系统。 2. Linux内核操作系统的构成: 内核、shell、文件系统、应用程序 -应用程序:文本编辑器等 -文件系统:文件存放在存储设备上的组织方…...
软件工程之静态建模
静态模型:有助于设计包、类名、属性和方法特征标记(但不是方法体)的定义,例如UML类图。 用例的关系: 扩展关系: 扩展关系允许一个用例(可选)扩展另一个用例(基用例&…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
