第5课 使用FFmpeg将rtmp流再转推到rtmp服务器

news2024/11/17 16:49:53

本课对应源文件下载链接:

https://download.csdn.net/download/XiBuQiuChong/88801992

 通过前面的学习,我们已经可以正常播放网络rtmp流及本地mp4文件。这节课,我们将在前面的基础上实现一个常用的转推功能:读取rtmp流或mp4文件并转推到rtmp服务器上实现直播转发功能。

一、最终实现的效果

上面左图为播放的rtmp流并将该流转推到另一台rtmp服务器,右图为用vlc播放的另一台rtmp服务器上被转发的流。

二、使用FFmpeg将rtmp流转推到另一台rtmp服务器​的原理

使用FFmpeg API 转码推流的一般过程如下:

1.引入ffmpeg库:在代码中引入ffmpeg库,以便使用其提供的功能。

2.打开输入文件:使用avformat_open_input()函数打开输入文件,并获取输入文件的相关信息。

3.查找流信息:使用avformat_find_stream_info()函数查找输入文件中的流信息,并将其存储在AVFormatContext结构体中。

4.创建输出上下文:使用avformat_alloc_output_context2()函数创建输出上下文,并设置输出格式。

5.添加输出流:根据输入文件的流信息,使用avformat_new_stream()函数创建输出流,并将其添加到输出上下文中。

6.设置编码参数:为输出流设置编码参数,包括编码器、编码器参数等。

7.输出文件:使用avio_open()函数打开输出文件,并将输出文件的相关信息存储在输出上下文中。

8.写入文件头:使用avformat_write_header()函数写入输出文件的文件头。

9.转码推流:循环读取输入文件的数据包,使用av_read_frame()函数读取数据包,然后使用avcodec_send_frame()函数发送数据包给编码器进行编码,再使用avcodec_receive_packet()函数接收编码后的数据包,最后使用av_interleaved_write_frame()函数将编码后的数据包写入输出流。

10.写入文件尾:使用av_write_trailer()函数写入输出文件的文件尾。

11.释放资源:释放所有的上下文、流和其他资源,使用avformat_close_input()函数关闭输入文件。

三、转推功能的具体实现

与rtmp流或mp4文件播放功能相比,转推功能只是在原来的基础上又增加了编码功能和向rtmp服务器的推送功能。为了降低难度,这节课的转推功能不涉及编码部分,只实现将拉取来的rtmp流直接进行转推。

1.为了与上节课的播放功能区分,新建或直接复制fmlp(Flash Media Live Player)类为一个新的fmlt(Flash Media Live Transcoder)类,并修改主对话框相应代码使fmlt能正常工作并实现正常的播放功能。

修改如下:

//#include "fmlp.h"
#include "fmlt.h"
………………
//fmlp *myFmlp = new fmlp();
fmlt *myFmlt = new fmlt();

2.与mp4文件相比,rtmp流转推实现起来相对容易,因此,我们先在原来的基础上实现rtmp流的转推功能。

(1)直接拷贝原fmlp.cpp的代码到fmt.cpp中,并定义转推到另一台rtmp服务器的流地址等变量:

//转码输出初始化	
	const char *outFileName = "rtmp://192.168.0.101/hk/cctv";		
	AVOutputFormat *outFormat = NULL;
	AVFormatContext *outFormatCtx = NULL;
	//定义输出音视频流
	AVStream *videoStream = NULL;
	AVStream *audioStream = NULL;

(2)打开输出流:

avformat_alloc_output_context2(&outFormatCtx, NULL, "flv", outFileName);

………………

         videoStream = avformat_new_stream(outFormatCtx, vDecodec);

         videoStream->id = outFormatCtx->nb_streams - 1;

         videoStream->codecpar->codec_tag = 0;

         avcodec_parameters_from_context(videoStream->codecpar, vDecodeCtx);

         audioStream = avformat_new_stream(outFormatCtx, aDecodec);

         audioStream->codecpar->codec_tag = 0;

         audioStream->id = outFormatCtx->nb_streams - 1;

         avcodec_parameters_from_context(audioStream->codecpar, aDecodeCtx);

         av_dump_format(outFormatCtx, 0, outFileName, 1);

         ret = avio_open2(&outFormatCtx->pb, outFileName, AVIO_FLAG_READ_WRITE, nullptr, nullptr);

         if (ret < 0){

                  return -1;

         }

         ret = avformat_write_header(outFormatCtx, NULL);

         if (ret < 0){

                  TRACE("ret:%d\n", ret);

                  return -1;

         }

(3)获取到原rtmp流并正常播放音视频后,将音视频包直接写入输出流:

if (normalPkt.stream_index == videoIndex) {

                          //原视频播放代码

                          normalPkt.stream_index = videoStream->index;

                          normalPkt.pts = currentTime;

                          normalPkt.dts = currentTime;

                          normalPkt.duration = currentTime;

                          normalPkt.pos = -1;

                          //enVideoPacket.flags = AV_PKT_FLAG_KEY;

                          if (normalPkt.size > 0){

                                   ret = av_interleaved_write_frame(outFormatCtx, &normalPkt);

                          }

                          av_packet_unref(&normalPkt);

                  }

                  else if (normalPkt.stream_index == audioIndex)

                  {                       

                          //原音频播放代码

                          normalPkt.stream_index = audioStream->index;

                          normalPkt.pts = currentTime;

                          normalPkt.dts = currentTime;

                          normalPkt.duration = currentTime;

                          normalPkt.pos = -1;

                          //enVideoPacket.flags = AV_PKT_FLAG_KEY;

                          if (normalPkt.size > 0){

                                   ret = av_interleaved_write_frame(outFormatCtx, &normalPkt);

                          }

                          av_packet_unref(&normalPkt);

          }

这样,就实现了在播放音视频的同时又能将该流转推到另一台服务器的功能。

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

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

相关文章

matlab|【EI复现】日前日内多阶段多时间尺度源荷储协调调度

目录 一、模型 二、程序运行 三、下载链接 多阶段多时间尺度的协调调度的优势是考虑新能源出力的波动性与随机性&#xff0c;减少需求响应负荷的不确定性对电网制定的日前调度计划准确性造成的影响&#xff0c;也就是能够更加精准的进行调度和分析&#xff0c;优化结果的可用…

(java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~

目录 冒泡排序(BubbleSort)&#xff1a; 代码详解&#xff1a; 冒泡排序的优化&#xff1a; 选择排序(SelectSort)&#xff1a; 代码详解&#xff1a; 插入排序&#xff08;InsertSort&#xff09;&#xff1a; 代码详解&#xff1a; 希尔排序(ShellSort)&#xff1a; 法一…

【数据结构与算法】之排序系列-20240202

这里写目录标题 一、389. 找不同二、414. 第三大的数三、455. 分发饼干四、506. 相对名次五、561. 数组拆分六、594. 最长和谐子序列 一、389. 找不同 简单 给定两个字符串 s 和 t &#xff0c;它们只包含小写字母。 字符串 t 由字符串 s 随机重排&#xff0c;然后在随机位置添…

双非本科准备秋招(14.3)—— java线程

创建和运行线程 1、使用Thread Slf4j(topic "c.Test1")public class Test1 {public static void main(String[] args) {Thread t new Thread("t1") {Overridepublic void run() {log.debug("running");}};t.start();​log.debug("runnin…

VUE项目导出excel

导出excel主要可分为以下两种&#xff1a; 1. 后端主导实现 流程&#xff1a;前端调用到导出excel接口 -> 后端返回excel文件流 -> 浏览器会识别并自动下载 场景&#xff1a;大部分场景都有后端来做 2. 前端主导实现 流程&#xff1a;前端获取要导出的数据 -> 把常规数…

Apache Paimon 文件布局设计

Apache Paimon 介绍 Apache Paimon 基础概念 一张表的所有文件都存储在一个基本目录下&#xff0c;Paimon 文件以分层方式组织。从快照文件开始&#xff0c;可以递归地访问表中的所有记录。 image.png Snapshot Files 所有的 snapshot 文件都存储在 snapshot 目录下&#xff0c…

【C语言刷题系列】喝汽水问题

文章目录 一、文章简介 1.先买再换 1.1 代码逻辑&#xff1a; 1.2 完整代码 1.3 运行结果 1.4 根据方法一总结优化 2.边买边换 2.1 代码逻辑&#xff1a; 2.2 完整代码 2.3 运行结果 一、文章简介 本文所述专栏——C语言经典编程问题 C语言刷题_倔强的石头106的博客…

【AI绘画UI+Windows部署】Fooocus:Controlnet原作者结合了sd的开源和Midjourney重新设计的UI

代码&#xff1a;https://github.com/lllyasviel/Fooocus windows一键启动包下载&#xff1a;https://github.com/lllyasviel/Fooocus/releases/download/release/Fooocus_win64_2-1-831.7z B站视频教程&#xff1a;AI绘画入门神器&#xff1a;Fooocus | 简化SD流程&#xff0c…

创建型模式-单例模式:定义、实现及应用

目录 一、模式定义二、针对问题1.解决的问题2.解决方案3.举个例子4.设计模式适合场景5.实现方式6.优缺点7.与其他模式的关系 三、代码实现 一、模式定义 单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型模式&#xff0c;用于限制某个类只能创建一个对象。它提…

【代码随想录】LC 455. 分发饼干

文章目录 前言一、题目1、原题链接2、题目描述 二、解题报告1、思路分析2、时间复杂度3、代码详解 前言 本专栏文章为《代码随想录》书籍的刷题题解以及读书笔记&#xff0c;如有侵权&#xff0c;立即删除。 一、题目 1、原题链接 455. 分发饼干 2、题目描述 二、解题报告 1、…

367. Valid Perfect Square(有效的完全平方数)

题目描述 给你一个正整数 num 。如果 num 是一个完全平方数&#xff0c;则返回 true &#xff0c;否则返回 false 。 完全平方数 是一个可以写成某个整数的平方的整数。换句话说&#xff0c;它可以写成某个整数和自身的乘积。 不能使用任何内置的库函数&#xff0c;如 sqrt(…

随着网络的快速发展,网络安全问题也日益凸显,遇到攻击该如何处理,如何抉择合适的防护方案

DexunCloud 经过研究发现当今世界&#xff0c;随着网络的快速发展&#xff0c;网络安全问题也日益凸显。其中&#xff0c;DDoS&#xff08;分布式拒绝服务&#xff09;攻击被认为是网络安全领域里最为严重的威胁之一。毫无疑问&#xff0c;DDoS攻击不仅可以导致网络服务中断&am…

【笔记】React Native实战练习(仿网易云游戏网页移动端)

/** * 如果系统看一遍RN相关官方文档&#xff0c;可能很快就忘记了。一味看文档也很枯燥无味&#xff0c; * 于是大概看了关键文档后&#xff0c;想着直接开发一个Demo出来&#xff0c;边学边写&#xff0c;对往后工作 * 开发衔接上能够更顺。这期间肯定会遇到各种各样的问题&a…

【数据结构】链表OJ面试题(题库+解析)

前言 还不清楚链表的码喵们可以看看前篇关于链表的详解 http://t.csdnimg.cn/X6t6P 1.链表面试题 既然已经懂得了链表该如何实现&#xff0c;那么现在就趁热打铁开始练习&#xff01;这里给码喵们整理了相对不错的一些OJ题来练习 1. 删除链表中等于给定值 val 的所有结点。 力…

RK3568平台 安卓hal3适配usb camera

一.RK安卓hal3 camera框架 Camera hal3 在 android 框架中所处的位置如上图&#xff0c; 对上&#xff0c;主要实现 Framework 一整套 API 接口&#xff0c;响应其 控制命令&#xff0c;返回数据与控制参数结果。 对下&#xff0c; 主要是通 V4l2 框架实现与 kernel 的交互。3a…

AI应用开发-git开源项目的一些问题及镜像解决办法

AI应用开发相关目录 本专栏包括AI应用开发相关内容分享&#xff0c;包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 AI应用开发流程概…

Redis核心技术与实战【学习笔记】 - 18.Redis 缓存被污染了,如何选择淘汰策略

前言 在一些常见下&#xff0c;有些数据被访问的次数非常少&#xff0c;甚至只会被访问一次。当这些数据请求后&#xff0c;还继续留存在缓存中的话&#xff0c;只会白白占用缓存的空间。这种情况就是缓存污染。 当缓存污染不严重时&#xff0c;只有少量数据占据缓存空间&…

题目:有1,2,3,4共四个数字,能组成多少个不相同而且无重复数字的三位数有多少个,都是多少?lua

这是作者的思路&#xff0c; 创建三个表&#xff0c; 第一个数是从四个数遍历&#xff0c; 第二个是数剔除第一个数进行遍历 第三个是剔除第一第二个数遍历 脚本如下 local a{1,2, 3, 4} local b{} local c{} local d{} local function copy(tbl) local ctbl{} for k,v in…

Flink CEP(基本概念)

Flink CEP 在Flink的学习过程中&#xff0c;我们已经掌握了从基本原理和核心层的DataStream API到底层的处理函数&#xff0c;再到应用层的Table API和SQL的各种手段&#xff0c;可以应对实际应用开发的各种需求。然而&#xff0c;在实际应用中&#xff0c;还有一类更为复…

大数据 - Hadoop系列《三》- MapReduce(分布式计算引擎)概述

上一篇文章&#xff1a; 大数据 - Hadoop系列《三》- HDFS&#xff08;分布式文件系统&#xff09;概述-CSDN博客 目录 12.1 针对MapReduce的设计构思 1. 如何对付大数据处理场景 2. 构建抽象编程模型 3. 统一架构、隐藏底层细节 12.2 分布式计算概念 12.3 MapReduce定义…