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("迭代失败…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...

华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...