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;
}

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

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

相关文章

优化|优化求解器自动调参

原文信息&#xff1a;MindOpt Tuner: Boost the Performance of Numerical Software by Automatic Parameter Tuning 作者&#xff1a;王孟昌 &#xff08;达摩院决策智能实验室MindOpt团队成员&#xff09; 一个算法开发者&#xff0c;可能会幻想进入这样的境界&#xff1a;算…

JWT开发详解

文章目录 一、JWT理论基础二、JWT使用实例2.1 服务端代码2.2 客户端代码 三、JWT流程 一、JWT理论基础 JSON Web Token&#xff08;JWT&#xff09;是一种开放标准&#xff08;RFC 7519&#xff09;&#xff0c;用于在网络上以紧凑且自包含的方式安全地传输信息。JWT 被设计为…

【Android】如何使用模拟器调试安卓项目

1、电脑安装逍遥模拟器&#xff0c;用来跑安卓项目。安装好模拟器之后&#xff0c;直接起安卓项目&#xff0c;自动会在选择设备处显示 2、如果前端是安卓后端是其他语言的话&#xff0c;这种前后端分离的模式&#xff0c;需要监听端口&#xff0c;原因是运行安卓和后端编译器都…

NC65 如何设置现金流量明细查询的查询框中核算账簿可多选??

NC65 如何设置现金流量明细查询的查询框中核算账簿可多选&#xff1f;&#xff1f; NC65 如何设置现金流量明细查询的查询框中核算账簿可多选&#xff1f;&#xff1f;效果如下图 解决方案二开&#xff0c;即在 nc.ui.gl.cashflowcase.CashFlowDetailQueryUI 的 onButtonQuer…

安装银河麒麟linux系统docker(docker-compose)环境,注意事项(一定能解决,有环境资源)

1&#xff1a;安装docker环境必须使用麒麟的版本如下 2&#xff1a;使用docker-compse up -d启动容器遇到的文件 故障1&#xff1a;如果运行docker-compose up 报“Cannot create redo log files because data files are corrupt or the database was not shut down cleanly a…

使用docker部署nacos分布式集群

本文目的 在服务器中部署nacos集群&#xff0c;并连接外置数据库关于外置的mysql部署和单例nacos如何部署请看下面的两个链接 如何使用docker部署mysql docker部署容器化mysql5.7-CSDN博客 如何使用docker部署nacos 容器化部署Nacos&#xff1a;从环境准备到启动-CSDN博客…

导航守卫有哪三种?

导航守卫主要分为三种&#xff1a; 全局前置守卫&#xff1a;使用 router.beforeEach 注册&#xff0c;作用是在路由切换开始前进行拦截和处理&#xff0c;可以用来进行一些全局的权限校验、登录状态检查等操作。 全局解析守卫&#xff1a;使用 beforeResolve 注册&#xff0c…

mfc140u.dll丢失的解决方法,以及针对每个解决mfc140u.dll丢失办法的优缺点

在使用电脑的过程中&#xff0c;有时会遇到一些与动态链接库文件&#xff08;DLL&#xff09;相关的错误。其中&#xff0c;mfc140u.dll丢失是一种常见的问题&#xff0c;它可能导致应用程序无法正常运行。在本文中&#xff0c;我们将探讨关于mfc140u.dll丢失的解决办法&#x…

WordPress主题WoodMart v7.3.2 WooCommerce主题和谐汉化版下载

WordPress主题WoodMart v7.3.2 WooCommerce主题和谐汉化版下载 WoodMart是一款出色的WooCommerce商店主题&#xff0c;它不仅提供强大的电子商务功能&#xff0c;还与流行的Elementor页面编辑器插件完美兼容。 主题文件在WoodMart Theme/woodmart.7.3.2.zip&#xff0c;核心在P…

目标检测YOLO实战应用案例100讲-基于机器视觉的水稻病虫害监测预警

目录 前言 国内外研究现状 国外研究现状 国内研究现状 2 相关理论与技术

利用 Pandoc + ChatGPT 优雅地润色论文,并保持 Word 公式格式:Pandoc将Word和LaTeX文件互相转化

论文润色完美解决方案&#xff1a;Pandoc 与 ChatGPT 的强强联合 写在最前面其他说明 一、通过 Pandoc 将 Word 转换为 LaTeX 的完整指南步骤 1: 安装 PandocWindows:macOS:Linux: 步骤 2: 准备 Word 文档步骤 3: 转换文档步骤 4: 检查并调整输出步骤 5: 编译 LaTeX 文档总结 二…

使用 DFS 轻松求解数独难题(C++ 的一个简单实现)

起因 都说懒惰是第一生产力&#xff0c;最近在玩数独游戏的时候&#xff0c;总会遇到拆解数独比较复杂的情况&#xff0c;就想着自己写个代码解题&#xff0c;解放双手。所以很快就写了一个简单的代码求解经典数独。拿来跑了几个最高难度的数独发现确实很爽&#xff01;虽说是…

Ubuntu 22.04安装Rust编译环境并且测试

我参考的博客是《Rust使用国内Crates 源、 rustup源 |字节跳动新的 Rust 镜像源以及安装rust》 lsb_release -r看到操作系统版本是22.04,uname -r看到内核版本是uname -r。 sudo apt install -y gcc先安装gcc&#xff0c;要是结果给我的一样的话&#xff0c;那么就是安装好了…

【SpringBoot篇】分页查询 | 扩展SpringMvc的消息转换器

文章目录 &#x1f6f8;什么是分页查询&#x1f339;代码实现⭐问题&#x1f384;解决方法 做了几个项目&#xff0c;发现在这几个项目里面&#xff0c;都实现了分页查询效果&#xff0c;所以就总结一下&#xff0c;方便学习 我们基于黑马程序员的苍穹外卖来讲解分页查询的要点…

go-zero对数据库的操作

一、go-zerro中结合gorm来操作mysql数据库 1、这里我这就直接结合gorm-gen的方式来实现数据库操作,关于gorm-gen可以参考官网 2、创建一个数据库&#xff0c;并且创建一个表 -- ------------------------ -- 用户表 -- ------------------------ DROP TABLE IF EXISTS user; C…

Java中如何通过路径表达式找值:XPath和JsonPath以及SpEL详解及对比

大家好&#xff0c;我是G探险者。 我们编程时&#xff0c;在前后端数据交互和传输过程中&#xff0c;往往需要对报文中的某个字段或者某个标签的值进行解析读取&#xff0c;报文通常是以json或者xml作为数据交换格式&#xff0c;而json和xml这两种格式的报文结构都是具备一定的…

docker容器自启动

场景 当服务器关机重启后&#xff0c;docker容器每次都要去docker start 容器id 怎么可以下次让它自启动呢&#xff1f; 解决 先 # docker ps -a 查到之前启动过的容器id # docker update --restartalways 容器id重启后&#xff0c;reboot&#xff0c;就不用再单独去启动容…

string类的总结

目录 1.为什么要学习string类 2.string的标准库 3.string类的常用接口说明 1.string类对象的常见构造 2.string类对象的容量操作 3.string类对象的3种遍历方法 3.1 [ ] 下标 3.2 基于范围的for循环 3.3 迭代器 4 string类对象的元素访问 4.1 operator[]&#xff1a; 4.…

【洛谷 P3853】[TJOI2007] 路标设置 题解(二分答案+循环)

[TJOI2007] 路标设置 题目背景 B 市和 T 市之间有一条长长的高速公路&#xff0c;这条公路的某些地方设有路标&#xff0c;但是大家都感觉路标设得太少了&#xff0c;相邻两个路标之间往往隔着相当长的一段距离。为了便于研究这个问题&#xff0c;我们把公路上相邻路标的最大…

目标检测—YOLO系列(二 ) 全面解读复现YOLOv1 PyTorch

精读论文 前言 从这篇开始&#xff0c;我们将进入YOLO的学习。YOLO是目前比较流行的目标检测算法&#xff0c;速度快且结构简单&#xff0c;其他的目标检测算法如RCNN系列&#xff0c;以后有时间的话再介绍。 本文主要介绍的是YOLOV1&#xff0c;这是由以Joseph Redmon为首的…