07-流媒体-RTMP推流
整体方案:
采集端:摄像头采集(YUV)->编码(YUV转H264)->写封装(H264转FLV)->RTMP推流
客户端:RTMP拉流->解封装(FLV转H264)->解码(H264转YUV)->YUV显示(SDL2)
程序:
推流时要启动服务器,方法在前面章节有描述
#include <stdio.h>#define __STDC_CONSTANT_MACROS#ifdef _WIN32
//Windows
extern "C"
{
#include "libavformat/avformat.h"
#include "libavutil/mathematics.h"
#include "libavutil/time.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavformat/avformat.h>
#include <libavutil/mathematics.h>
#include <libavutil/time.h>
#ifdef __cplusplus
};
#endif
#endifint main(int argc, char* argv[])
{AVOutputFormat *ofmt = NULL;//输入对应一个AVFormatContext,输出对应一个AVFormatContext//(Input AVFormatContext and Output AVFormatContext)AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;AVPacket pkt;const char *in_filename, *out_filename;int ret, i;int videoindex=-1;int frame_index=0;int64_t start_time=0;in_filename = "demo.flv";//输入URL(Input file URL)out_filename = "rtmp://192.168.6.139:1935/live/stream";//输出 URL(Output URL)[RTMP]av_register_all();//Networkavformat_network_init();//输入(Input)if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {printf( "Could not open input file.");goto end;}if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {printf( "Failed to retrieve input stream information");goto end;}for(i=0; i<ifmt_ctx->nb_streams; i++) if(ifmt_ctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){videoindex=i;break;}av_dump_format(ifmt_ctx, 0, in_filename, 0);//输出(Output)avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_filename); //RTMP//avformat_alloc_output_context2(&ofmt_ctx, NULL, "mpegts", out_filename);//UDPif (!ofmt_ctx) {printf( "Could not create output context\n");ret = AVERROR_UNKNOWN;goto end;}ofmt = ofmt_ctx->oformat;for (i = 0; i < ifmt_ctx->nb_streams; i++) {//根据输入流创建输出流(Create output AVStream according to input AVStream)AVStream *in_stream = ifmt_ctx->streams[i];AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);if (!out_stream) {printf( "Failed allocating output stream\n");ret = AVERROR_UNKNOWN;goto end;}//复制AVCodecContext的设置(Copy the settings of AVCodecContext)ret = avcodec_copy_context(out_stream->codec, in_stream->codec);if (ret < 0) {printf( "Failed to copy context from input to output stream codec context\n");goto end;}out_stream->codec->codec_tag = 0;if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;}//Dump Format------------------av_dump_format(ofmt_ctx, 0, out_filename, 1);//打开输出URL(Open output URL)if (!(ofmt->flags & AVFMT_NOFILE)) {ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);if (ret < 0) {printf( "Could not open output URL '%s'", out_filename);goto end;}}//写文件头(Write file header)ret = avformat_write_header(ofmt_ctx, NULL);if (ret < 0) {printf( "Error occurred when opening output URL\n");goto end;}start_time=av_gettime();while (1) {AVStream *in_stream, *out_stream;//获取一个AVPacket(Get an AVPacket)ret = av_read_frame(ifmt_ctx, &pkt);if (ret < 0)break;//FIX:No PTS (Example: Raw H.264)//Simple Write PTSif(pkt.pts==AV_NOPTS_VALUE){//Write PTSAVRational time_base1=ifmt_ctx->streams[videoindex]->time_base;//Duration between 2 frames (us)int64_t calc_duration=(double)AV_TIME_BASE/av_q2d(ifmt_ctx->streams[videoindex]->r_frame_rate);//Parameterspkt.pts=(double)(frame_index*calc_duration)/(double)(av_q2d(time_base1)*AV_TIME_BASE);pkt.dts=pkt.pts;pkt.duration=(double)calc_duration/(double)(av_q2d(time_base1)*AV_TIME_BASE);}//Important:Delayif(pkt.stream_index==videoindex){AVRational time_base=ifmt_ctx->streams[videoindex]->time_base;AVRational time_base_q={1,AV_TIME_BASE};int64_t pts_time = av_rescale_q(pkt.dts, time_base, time_base_q);int64_t now_time = av_gettime() - start_time;if (pts_time > now_time)av_usleep(pts_time - now_time);}in_stream = ifmt_ctx->streams[pkt.stream_index];out_stream = ofmt_ctx->streams[pkt.stream_index];/* copy packet *///转换PTS/DTS(Convert PTS/DTS)pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);pkt.pos = -1;//Print to Screenif(pkt.stream_index==videoindex){printf("Send %8d video frames to output URL\n",frame_index);frame_index++;}//ret = av_write_frame(ofmt_ctx, &pkt);ret = av_interleaved_write_frame(ofmt_ctx, &pkt);if (ret < 0) {printf( "Error muxing packet\n");break;}av_free_packet(&pkt);}//写文件尾(Write file trailer)av_write_trailer(ofmt_ctx);
end:avformat_close_input(&ifmt_ctx);/* close output */if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))avio_close(ofmt_ctx->pb);avformat_free_context(ofmt_ctx);if (ret < 0 && ret != AVERROR_EOF) {printf( "Error occurred.\n");return -1;}return 0;
}
相关文章:
07-流媒体-RTMP推流
整体方案: 采集端:摄像头采集(YUV)->编码(YUV转H264)->写封装(H264转FLV)->RTMP推流 客户端:RTMP拉流->解封装(FLV转H264)…...

Neo4j安装(Docker中安装Neo4j)
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...
面试求职者
顾x文 SQLite3数据的使用实现了多线程UDP数据收发功能Qt多线程的同步和异步熟悉GDB的调试了解Mysql的性能优化熟悉常见算法:快速排序、希尔排序、归并排序基于Nginx C Mysql Python ICE开发熟练Boost库负责搭建后台服务端,使用Nginx展示前端界面&am…...

Java NIO 详解
一、NIO简介 NIO 是 Java SE 1.4 引入的一组新的 I/O 相关的 API,它提供了非阻塞式 I/O、选择器、通道、缓冲区等新的概念和机制。相比与传统的 I/O 多出的 N 不是单纯的 New,更多的是代表了 Non-blocking 非阻塞,NIO具有更高的并发性、可扩…...
css设置下划线
css中设置下划线的方法 在CSS中可以使用text-decoration属性或border-bottom属性来给字体设置下划线样式。 1、使用text-decoration:underline;设置下划线样式 CSS的text-decoration属性用于指定添加到文本的修饰,其underline属性值可以定义文本下的一条线。 语…...

【献给过去的自己】栈实现计算器(C语言)
背景 记得在刚学C语言时,写了一篇栈实现计算器-CSDN博客文章。偶然间看到了文章的阅读量以及评论,居然有1.7w的展现和多条博友的点评,反馈。 现在回过头来看,的确有许多不严谨的地方,毕竟当时分享文章时,还…...

如何利用ChatGPT撰写学术论文?
在阅读全文前请注意,本文是利用ChatGPT“辅助完成”而不是“帮写”学术论文,请一定要注意学术规范! 本文我将介绍如何使用清晰准确的“指令”让ChatGPT帮助我们在论文写作上提高效率,希望通过本文的指导,读者能够充分…...
【PG】PostgreSQL高可用方案repmgr管理之配置文件
1 配置文件 1.1 配置文件格式 repmgr.conf是一个纯文本文件,每行包含一个参数/值组合。 空格是无关紧要的(除了在带引号的参数值内),并且空行将被忽略。#将该行的其余部分指定为注释。不是简单标识符或数字的参数值应该用单引号…...
labelme自动标注工具
可以实现多图中相同目标的追踪,自动标注目标位置,速度极快,有需要评论...

【C++学习手札】模拟实现vector
🎬慕斯主页:修仙—别有洞天 ♈️今日夜电波:くちなしの言葉—みゆな 0:37━━━━━━️💟──────── 5:28 🔄 ◀️ ⏸ ▶️ ☰…...
Python将图片按照表格形式排列
图片按照表格的形式排列,可以使用图像处理库Pillow来实现 事例代码 from PIL import Image, ImageDraw# 创建一个画布,用来存放排列后的图片 canvas Image.new(RGB, (800, 600), white)# 读取图片 im1 Image.open(image1.jpg) im2 Image.open(image…...
Linux 简要命令记录
1、设置时区: #设为上海: timedatectl set-timezone Asia/Shanghai #搜索特定时区 timedatectl list-timezone2、修改时间: #设定系统时间 date -s "2023-11-16 22:30:00" #同步写入BIOS hwclock -w3、fdisk分区 rootheihei:~# …...
深度学习与深度强化学习
1. 深度学习中卷积层的作用是什么?全连接层的作用是什么?二者有什么联系和区别? 在深度学习中,卷积层(Convolutional Layer)和全连接层(Fully Connected Layer)是神经网络中常见的两…...
C++函数重载中形参是引用类型和常量引用类型的调用方法
void fun(int &a) {cout<<"调用func(int &a)<<endl; }void fun(const int &a) {cout<<"调用func(const int &a)<<endl; }int main() {// 1.调用引用类型的函数int a10;func(a);// 2.调用常量引用类型的函数,因为…...

Quest 3期间Sui上游戏处理了数百万笔交易
Sui固有的可扩展性和低且可预测的gas费使其成为Web3游戏的理想平台。在Quest 3中,参与的游戏项目处理了数百万笔交易,这毫无疑问地展示了Sui卓越的能力。 Quest 3的主题是游戏,让开发者有机会向潜在玩家介绍他们激动人心的创作。鼓励这些玩家…...
Python中如何定义类、基类、函数和变量?
在Python中,定义类、基类、函数和变量是非常常见的操作。以下是简单的示例: 定义类: class Animal:def __init__(self, name):self.name namedef make_sound(self):passclass Dog(Animal):def make_sound(self):return "Woof!"上…...

打开文件 和 文件系统的文件产生关联
补充1:硬件级别磁盘和内存之间数据交互的基本单位 OS的内存管理 内存的本质是对数据临时存/取,把内存看成很大的缓冲区 物理内存和磁盘交互的单位是4KB,磁盘中未被打开的文件数据块也是4KB,所以磁盘中页帧也是4KB,内存…...

【Rust】快速教程——模块mod与跨文件
前言 道尊:没有办法,你的法力已经消失,我的法力所剩无几,除非咱们重新修行,在这个世界里取得更多法力之后,或许有办法下降。——《拔魔》 \;\\\;\\\; 目录 前言跨文件mod多文件mod 跨文件mod //my_mod.rs…...

crontab定时任务是否执行
centos查看 crontab 是否启动 systemctl status crond.service 查看cron服务的启动状态 systemctl start crond.service 启动cron服务[命令没有提示] systemctl stop crond.service 停止cron服务[命令没有提示] systemctl restart crond.service 重启cron服务[命令没有提示] s…...
MATLAB程序设计:牛顿迭代法
function xnewton(x0,e,N,fx) %输入x0,误差限e,迭代次数N和函数Fx k1; while k<Nif subs(diff(fx),x0)0disp("输出奇异标志");break;endx1x0-subs(fx,x0)/subs(diff(fx),x0);if abs(x1-x0)<ebreak;endx0x1;kk1; end if k<Ndisp(x1); elsedisp("迭代失败…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...
用递归算法解锁「子集」问题 —— LeetCode 78题解析
文章目录 一、题目介绍二、递归思路详解:从决策树开始理解三、解法一:二叉决策树 DFS四、解法二:组合式回溯写法(推荐)五、解法对比 递归算法是编程中一种非常强大且常见的思想,它能够优雅地解决很多复杂的…...