FFmpeg实现RTSP推流

以下是的示例代码,演示了如何从本地文件(mp4)读取媒体流,并将其推送到 RTSP 服务器:
代码未经验证,供参考

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>#define RTPPKT_LEN 1400// TCP Socket
int tcpSocket;// TCP 发送函数
int tcp_write_buffer(void* opaque, uint8_t* buf, int buf_size) {ssize_t sentBytes = send(tcpSocket, buf, buf_size, 0);if (sentBytes < 0) {perror("TCP 发送失败");return -1;}return 0;
}int main() {// 初始化 FFmpeg 库av_register_all();avformat_network_init();// 创建 TCP SockettcpSocket = socket(AF_INET, SOCK_STREAM, 0);if (tcpSocket < 0) {perror("无法创建 TCP Socket");return -1;}// 连接目标服务器struct sockaddr_in destAddr;memset(&destAddr, 0, sizeof(destAddr));destAddr.sin_family = AF_INET;destAddr.sin_port = htons(1234); // 设置目标端口号destAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置目标 IP 地址int ret = connect(tcpSocket, (struct sockaddr*)&destAddr, sizeof(destAddr));if (ret < 0) {perror("无法连接到服务器");return -1;}// 创建 AVIO 缓存空间unsigned char* outBuffer = (unsigned char*)av_malloc(RTPPKT_LEN);// 创建 AVIO 上下文AVIOContext* avioOut = avio_alloc_context(outBuffer, RTPPKT_LEN, 1, nullptr, nullptr, tcp_write_buffer, nullptr);if (!avioOut) {printf("无法创建 AVIO 上下文\n");return -1;}// 创建输出格式上下文AVFormatContext* outputFormatCtx = nullptr;const std::string serverUrl = "rtsp://127.0.0.1/live/stream"; // 修改为您的 RTSP 服务器地址ret = avformat_alloc_output_context2(&outputFormatCtx, nullptr, "rtsp", serverUrl.c_str());if (ret < 0) {printf("无法创建输出格式上下文\n");return -1;}outputFormatCtx->pb = avioOut;// 打开输入文件AVFormatContext* inputFormatCtx = nullptr;const std::string inputUrl = "input.mp4"; // 修改为您的输入文件路径ret = avformat_open_input(&inputFormatCtx, inputUrl.c_str(), nullptr, nullptr);if (ret != 0) {printf("无法打开输入文件:%s\n", inputUrl.c_str());return -1;}// 获取流信息ret = avformat_find_stream_info(inputFormatCtx, nullptr);if (ret < 0) {printf("无法获取流信息\n");return -1;}// 复制输入流的参数到输出流for (unsigned int i = 0; i < inputFormatCtx->nb_streams; i++) {AVStream* inputStream = inputFormatCtx->streams[i];AVCodec* codec = avcodec_find_decoder(inputStream->codecpar->codec_id);AVStream* outputStream = avformat_new_stream(outputFormatCtx, codec);if (!outputStream) {printf("无法创建输出流\n");return -1;}ret = avcodec_parameters_copy(outputStream->codecpar, inputStream->codecpar);if (ret < 0) {printf("无法复制编解码器参数\n");return -1;}}// 写入输出头部ret = avformat_write_header(outputFormatCtx, nullptr);if (ret < 0) {printf("无法写入输出头部\n");return -1;}// 开始读取和发送数据包AVPacket packet;while (av_read_frame(inputFormatCtx, &packet) >= 0) {// 发送数据包到输出上下文ret = av_interleaved_write_frame(outputFormatCtx, &packet);if (ret < 0) {printf("无法发送数据包\n");return -1;}av_packet_unref(&packet);}// 发送 RTSP TEARDOWN 请求av_write_trailer(outputFormatCtx);// 关闭 RTSP 会话avio_closep(&outputFormatCtx->pb);// 关闭 Socketclose(tcpSocket);// 释放资源avformat_close_input(&inputFormatCtx);avformat_free_context(inputFormatCtx);avformat_free_context(outputFormatCtx);avio_context_free(&avioOut);av_free(outBuffer);return 0;
}

在这个示例中,我们使用 avformat_open_input 函数打开输入文件(mp4),然后读取并发送数据包到输出上下文。通过 av_interleaved_write_frame 函数将数据包写入输出上下文。

请注意,您需要将输入文件的路径(input.mp4)和目标 RTSP 服务器地址(rtsp://127.0.0.1/live/stream)根据实际情况进行修改。

以下是上述代码的整体流程:

  1. 初始化 FFmpeg 库,包括注册所需的组件和网络模块。

  2. 创建 TCP Socket,并连接到目标服务器。

  3. 创建 AVIO 缓存空间,并使用 avio_alloc_context 函数创建 AVIO 上下文,用于将数据发送到 RTSP 服务器。

  4. 创建输出格式上下文,设置推流的目标 URL(RTSP 服务器地址)。

  5. 打开输入文件(本地 mp4 文件),创建输入格式上下文,并读取流信息。

  6. 复制输入流的参数到输出流,为每个输入流创建一个对应的输出流。

  7. 写入输出头部,使用 avformat_write_header 函数将输出格式上下文的头部写入输出上下文。

  8. 开始读取输入文件并发送数据包。使用 av_read_frame 函数从输入文件中读取数据包,然后通过 av_interleaved_write_frame 函数将数据包发送到输出上下文。

  9. 发送 RTSP TEARDOWN 请求,调用 av_write_trailer 函数向输出上下文发送 RTSP TEARDOWN 请求,结束 RTSP 会话。

  10. 关闭 RTSP 会话和 TCP Socket。

  11. 释放资源,包括关闭输入文件、释放输入和输出格式上下文、释放 AVIO 上下文以及释放相关内存缓冲区。

以上是整体流程的简要描述。实际应用中,您可能需要根据具体需求进行更多的配置和处理,如设置音频流、传输参数、验证身份等。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

项目中webpack优化配置(1)

项目中webpack优化配置 一. 开发效率&#xff0c; 体验 1. DLL&#xff08;开发过程中减少构建时间和增加应用程序的性能&#xff09; 使用 DllPlugin 进行分包&#xff0c;使用 DllReferencePlugin(索引链接) 对 manifest.json 引用&#xff0c;让一些基本不会改动的代码先…

easyexcle处理导出合并单元格图片填充

GetMapping("getStyleSummaryExport") ApiOperation("款式汇总报表--导出") ApiImplicitParams({ApiImplicitParam(name Constant.PAGE, value "当前页码&#xff0c;从1开始", paramType "query", dataType "int"),Api…

jvm相关命令操作

查看jvm使用情况 jmap -heap PID 查看线程使用情况 jstack pid 查看当前线程数 jstack 21294 |grep -E (#[0-9]) -o -c 查看系统线程数 top -H top -Hp pid #查看具体的进程中的线程信息 使用 jps 命令查看配置了JVM的服务 查看某个进程JVM的GC使用情况 jstat -gc 进程…

STM32G4x FLASH 读写(修改HAL库驱动)

主要工作就是把HAL的超时用LL库延时替代&#xff0c;保留了中断擦写模式、轮询等待擦写&#xff0c;待验证哈。 笔者用的芯片为STM32G473CBT6 128KB Flash&#xff0c;开环环境为CUBEMXMDK5.32&#xff0c;因为G4已经没有标准库了&#xff0c;笔者还是习惯使用标准库的开发方式…

快速能访问服务器的文件

1、背景 访问ubuntu上的文件 2、方法 python3 -m http.server 8081 --directory /home/ NAS 共享访问协议 — NFS、SMB、FTP、WebDAV 各有何优势&#xff1f;http://1 Ubuntu 搭建文件服务器&#xff08;Nginx&#xff09;

FreeSWITCH回铃音补偿

回铃音介绍 回铃音就是拨打电话时&#xff0c;电话接通之前听到的嘟嘟的声音&#xff0c;如果拨打了开通了彩铃的手机&#xff0c;听到的是音乐声&#xff0c;彩铃也是一种回铃音&#xff0c;5G时代&#xff0c;又有了视频彩铃这样更新的回铃音方式了。 SIP信令之回铃音 在s…

Git初始

一)git的介绍: 1)假设现在有一个文档&#xff0c;你的老板要求你针对于这份文件进行修改&#xff0c;进行完成的修改的版本是版本1&#xff0c;接下来是文档2&#xff0c;修改完文档2以后&#xff0c;接下来老板还不同意&#xff0c;于是又有了文档三&#xff0c;文档四&#x…

Java 干净的Stream,Lambda代码写法

目录 一. 前期准备1.1 各种实体类1.2 生成List<CommonUser>的方法1.3 需求 二. 难以阅读的Lambda表达式三. 干净的Lambda表达式四. 效果 一. 前期准备 1.1 各种实体类 ⏹Address实体类&#xff0c;用来存储地址 import lombok.Builder; import lombok.Getter;Builder …

力扣刷题记录(17)LeetCode:416、1049

416. 分割等和子集 可以将该问题看成是一个背包问题。背包的容量就是nums数组和的一半。我们如果能够将背包装满就意味着可以将数组分割成两个元素和相等的子集。 1.确定dp[i]的含义 索引i表示背包的容量&#xff0c;dp[i]表示当前容量能够装载的最大值 2.确定动态转移方程 …

Uniapp + Vue3 封装请求工具挂载全局

新建request.js工具类 const http {// baseUrl 地址baseUrl: http://localhost:8080,// 请求方法request(config) {// config&#xff1a;请求配置对象&#xff0c;具体参照uniapp文档config beforeRequest(config)// 请求地址拼接config.url this.baseUrl config.url// 异…

前端性能优化四:精简html代码

1. 精简HTML代码: ①. 减少HTML嵌套,层级关系缩小.②. 减少DOM节点数.③. 减少无语义代码:a. 如:<div class"clear"></div>消除浮动,或者用css的方式处理.④. 删除http或者https:a. 如果URL的协议头恶化当前页面的协议头一致的.b. 或者此URL在多个协议头…

Linux-----14、vim

# vim Linux平台下的文本编辑器&#xff1a; emacs、nano、gedit、vi、vim vi&#xff08;visual editor&#xff09;编辑器通常被简称为vi&#xff0c;它是Linux和Unix系统上最基本的文本编辑器&#xff0c;类似于Windows 系统下的记事本。学会它后&#xff0c;我们将在Linu…

Vue数组变更方法和替换方法

一、可以引起UI界面变化 Vue 将被侦听的数组的变更方法进行了包裹&#xff0c;所以它们也将会触发视图更新。这些被包裹过的方法包括&#xff1a; push()pop()shift()unshift()splice()sort()reverse() 以上七个数组都会改变原数组&#xff0c;下面来分别讲解它们的区别&…

【Unity】【WebRTC】如何用Unity而不是浏览器接收远程画面

【背景】 之前几篇我们讨论了如何设置信令服务器&#xff0c;如何发送画面给远端以及如何用浏览器查看同步画面&#xff0c;今天来讨论如何实现Unity内部接收画面。 看本篇之前请先看过之前将web服务器设置和基本远程画面功能的几篇博文。&#xff08;同专栏下查看&#xff09…

Linux 脚本监控cpu输出到日志,每秒执行1次

vi test.sh while true; doecho date "%Y-%m-%d %H:%M:%S"", "$(top -bn1 | grep "Cpu(s)" | awk {print $1$2$3}) >> cpu_log.txtsleep 1 done top -bn1 | grep "Cpu(s)" 表示打印top命令的输出结果。 sleep 1 表示睡眠1秒…

TDengine 签约中船九院,助力航运业智能化转型升级

在大数据时代背景下&#xff0c;船舶智能化已经成为船舶制造与航运领域发展的必然趋势。智能船舶作为《中国制造 2025》中明确重点发展的领域&#xff0c;代表了船舶未来的方向&#xff0c;对于航运业的转型升级至关重要。其中&#xff0c;大数据的处理和运用成为船舶智能化转型…

每日一题(LeetCode)----栈和队列--逆波兰表达式求值

每日一题(LeetCode)----栈和队列–逆波兰表达式求值 1.题目&#xff08;150. 逆波兰表达式求值&#xff09; 给你一个字符串数组 tokens &#xff0c;表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意&#xff1a; 有效的算…

如何通过宝塔面板搭建一个MySQL数据库服务并实现无公网ip远程访问?

文章目录 前言1.Mysql服务安装2.创建数据库3.安装cpolar3.2 创建HTTP隧道 4.远程连接5.固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 宝塔面板的简易操作性,使得运维难度降低,简化了Linux命令行进行繁琐的配置,下面简单几步,通过宝塔面板cp…

python-dlib实现人脸提取和分割

效果 → 参考资料和资源 GitHub - Onwaier/SegfaceAndAlignByDlib: 用dlib实现脸部分割和人脸对齐 shape_predictor_68_face_landmarks.dat 下载地址_shape_predictor_68_face_landmarks.dat下载-CSDN博客 未运行的参考资料 dlib实现脸部分割与人脸对齐 - 知乎 py代码 &…

自定义通用物联网网关的MIB结构的参考

文章目录 说明参考代码开源项目地址 说明 由于时间有限&#xff0c;本人精力有限&#xff0c;所以给出的网关MIB结构&#xff0c;并非完美&#xff01;本文网关MIB结构的结构定义构思在使用MIB builder自定义物联网网关的MIB结构欢迎小伙伴&#xff0c;点赞、关注和评论&#…