ffmpeg c++代码推流RTSP/RTMP(命令行推流)
由于ffmpeg推出的rtsp或者rtmp端口需要Listen,所以需要开启端口TCP/UDP,之后采用ffmpeg向端口推送数据
第一,安装rtsp-simple-server
release下载地址https://github.com/aler9/rtsp-simple-server/releases/tag/v0.20.1
源码下载github地址
下载后解压后配置好端口,运行执行文件即可进行端口监听。
./rtsp-simple-server
第二,测试
FFmpeg 常用的命令行参数有
-c:指定编码器-c copy:直接复制,不经过重新编码(这样比较快)-c:v:指定视频编码器-c:a:指定音频编码器-i:指定输入文件-an:去除音频流,不处理音频-vn:去除视频流,不处理视频-preset:指定输出的视频质量,会影响文件的生成速度,候选值有:ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow.-y:不经过确认,输出时直接覆盖同名文件-vcodec: 设定视频编解码器,未设定时则使用与输入流相同的编解码器-b: 设定视频流量,默认为200Kbit/s-r: 设定帧速率,默认为25-s: 设定画面的宽与高-aspect: 设定画面的比例-ss: 开始时间# 音频参数-ar: 设定采样率-ac: 设定声音的Channel数-acodec: 设定声音编解码器,未设定时则使用与输入流相同的编解码器-an: 不处理音频
转码
H264 转 MP4
$ ffmpeg -i "xx.h264" -c:v copy -f mp4 "xx.mp4"
MP4 转 TS
ffmpeg -i xx.mp4 -c copy -vbsf h264_mp4toannexb faded.ts
推流
第三,引用头文件
代码推送视频
#include <iostream>extern "C"
{#include "libavformat/avformat.h"
#include "libavutil/mathematics.h"
#include "libavutil/time.h"
};int avError(int errNum);int main(int argc, char* argv[]){//输入文件const char *fileAddress = "../xx.mp4";//推流地址const char *rtmpAddress = "rtsp://0.0.0.0:8554/test";//注册所有库av_register_all();//初始化网络库avformat_network_init();// 输入流处理部分 ///AVFormatContext *ictx = NULL;//打开文件int ret = avformat_open_input(&ictx, fileAddress, 0, NULL);if (ret < 0){return avError(ret);}std::cout << "avformat_open_input succeeded" << std::endl;//获取流信息ret = avformat_find_stream_info(ictx, 0);if (ret != 0){return avError(ret);}//打印视频信息av_dump_format(ictx, 0, fileAddress, 0);// 输出流处理部分 ///AVFormatContext *octx = NULL;//创建输出上下文ret = avformat_alloc_output_context2(&octx, NULL, "rtsp", rtmpAddress); // ret = avformat_alloc_output_context2(&octx, NULL, "rtsp", rtmpAddress); if (ret < 0) {return avError(ret);}std::cout << "avformat_alloc_output_context2 succeeded" << std::endl;//配置输出流for (int i = 0; i < ictx->nb_streams; i++) {//创建一个新的流AVStream *outStream = avformat_new_stream(octx, ictx->streams[i]->codec->codec);if (!outStream) {return avError(0);}//复制配置信息ret = avcodec_parameters_copy(outStream->codecpar, ictx->streams[i]->codecpar);if (ret < 0) {return avError(ret);}outStream->codec->codec_tag = 0;}//打印输出流的信息av_dump_format(octx, 0, rtmpAddress, 1);// 准备推流 /////打开ioret = avio_open(&octx->pb, rtmpAddress, AVIO_FLAG_WRITE);if (ret < 0) {avError(ret);}//写入头部信息ret = avformat_write_header(octx, NULL);if ( ret < 0) {avError(ret);}std::cout << "avformat_write_header succeeded" << std::endl;//推流每一帧数据AVPacket avPacket;long long startTime = av_gettime();while (true){ret = av_read_frame(ictx, &avPacket);if (ret < 0 ){break;}std::cout << avPacket.pts << " " << std::flush;//计算转换时间戳//获取时间基数AVRational itime = ictx->streams[avPacket.stream_index]->time_base;AVRational otime = octx->streams[avPacket.stream_index]->time_base;avPacket.pts = av_rescale_q_rnd(avPacket.pts, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_NEAR_INF));avPacket.dts = av_rescale_q_rnd(avPacket.dts, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_NEAR_INF));//到这一帧经历了多长时间avPacket.duration = av_rescale_q_rnd(avPacket.duration, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_NEAR_INF));avPacket.pos = -1;//视频帧推送速度if (ictx->streams[avPacket.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){AVRational tb = ictx->streams[avPacket.stream_index]->time_base;//已经过去的时间long long now = av_gettime() - startTime;long long dts = 0;dts = avPacket.dts * (1000 * 1000 * av_q2d(tb));if (dts > now){av_usleep(dts - now);}}ret = av_interleaved_write_frame(octx, &avPacket);if (ret < 0){break;}}std::cin.get();return 0;
}int avError(int errNum) {char buf[1024];//获取错误信息av_strerror(errNum, buf, sizeof(buf));std::cout << " failed! " << buf << std::endl;return -1;
}
代码推送图片
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>#include <opencv2/imgcodecs.hpp>
#include <opencv2/core/mat.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;//FFMPEG
extern "C"
{#include <libswscale/swscale.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
#pragma comment(lib, "swscale.lib")
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avformat.lib")int main()
{VideoCapture capture(0);const char *outUrl;outUrl = "rtsp://0.0.0.0:8554/test";//注册所有的编解码器avcodec_register_all();//注册所有的封装器av_register_all();//注册所有网络协议avformat_network_init();//像素格式转换上下文SwsContext *vsc = NULL;//输出的数据结构AVFrame *yuv = NULL;//编码器上下文AVCodecContext *vc = NULL;//rtmp flv 封装器AVFormatContext *ic = NULL;AVOutputFormat *ofmt = NULL;int inWidth = 4160;int inHeight = 1024;int fps = 16;///2 初始化格式转换上下文vsc = sws_getCachedContext(vsc,inWidth, inHeight, AV_PIX_FMT_BGR24, //源宽、高、像素格式inWidth, inHeight, AV_PIX_FMT_YUV420P,//目标宽、高、像素格式SWS_BICUBIC, // 尺寸变化使用算法0, 0, 0 );if (!vsc){}///3 初始化输出的数据结构yuv = av_frame_alloc();yuv->format = AV_PIX_FMT_YUV420P;yuv->width = inWidth;yuv->height = inHeight;yuv->pts = 0;//分配yuv空间int ret = av_frame_get_buffer(yuv, 32);if (ret != 0){char buf[1024] = { 0 };av_strerror(ret, buf, sizeof(buf) - 1);}///4 初始化编码上下文//a 找到编码器AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264);if (!codec){}//b 创建编码器上下文vc = avcodec_alloc_context3(codec);if (!vc){// throw exception("avcodec_alloc_context3 failed!");}//c 配置编码器参数vc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; //全局参数vc->codec_id = codec->id;vc->thread_count = 8;vc->bit_rate = 50 * 1024 * 8;//压缩后每秒视频的bit位大小 50kBvc->width = inWidth;vc->height = inHeight;vc->time_base = { 1,fps };vc->framerate = { fps,1 };//画面组的大小,多少帧一个关键帧vc->gop_size = 50;vc->max_b_frames = 0;vc->pix_fmt = AV_PIX_FMT_YUV420P;//AV_PIX_FMT_RGB24 AV_PIX_FMT_YUV420P//d 打开编码器上下文ret = avcodec_open2(vc, codec, 0);if (ret != 0){char buf[1024] = { 0 };av_strerror(ret, buf, sizeof(buf) - 1);//throw exception(buf);}cout << "avcodec_open2 success!" << endl;///5 输出封装器和视频流配置//a 创建输出封装器上下文ret = avformat_alloc_output_context2(&ic, NULL, "rtsp", outUrl);if (ret != 0){char buf[1024] = { 0 };av_strerror(ret, buf, sizeof(buf) - 1);//throw exception(buf);}ofmt = ic->oformat;//b 添加视频流 AVStream *vs = avformat_new_stream(ic, codec);if (!vs){// throw exception("avformat_new_stream failed");}ret = avcodec_parameters_from_context(vs->codecpar, vc);av_dump_format(ic, 0, outUrl, 1);//打开rtmp 的网络输出IOif (!(ofmt->flags & AVFMT_NOFILE)){ret = avio_open(&ic->pb, outUrl, AVIO_FLAG_WRITE);if (ret != 0){char buf[1024] = { 0 };av_strerror(ret, buf, sizeof(buf) - 1);//throw exception(buf);}}//写入封装头ret = avformat_write_header(ic, NULL);if (ret != 0){char buf[1024] = { 0 };av_strerror(ret, buf, sizeof(buf) - 1);//throw exception(buf);}AVPacket pack;memset(&pack, 0, sizeof(pack));int vpts = 0;cv::Mat color_image=cv::imread("../11.jpg");//change picturewhile (1){//Mat color_image; //定义一个Mat类变量frame,用于存储每一帧的图像 // capture >> color_image; //读取当前帧 //若视频完成播放,退出循环 /*if (color_image.empty()) { cout << "1111111111111 break!" << endl; break; }*////ffmpeg推流部分//rgb to yuvuint8_t *indata[AV_NUM_DATA_POINTERS] = { 0 };indata[0] = color_image.data;int insize[AV_NUM_DATA_POINTERS] = { 0 };//一行(宽)数据的字节数insize[0] = color_image.cols * color_image.elemSize();int h = sws_scale(vsc, indata, insize, 0, color_image.rows, //源数据yuv->data, yuv->linesize);cout << color_image.rows << endl; if (h <= 0){continue;}//cout << h << " " << flush;///h264编码yuv->pts = vpts;vpts++;ret = avcodec_send_frame(vc, yuv);if (ret != 0)continue;ret = avcodec_receive_packet(vc, &pack);if (ret != 0 || pack.size > 0){//cout << "*" << pack.size << flush;}else{continue;}//推流pack.pts = av_rescale_q(pack.pts, vc->time_base, vs->time_base);pack.dts = av_rescale_q(pack.dts, vc->time_base, vs->time_base);pack.duration = av_rescale_q(pack.duration, vc->time_base, vs->time_base);ret = av_interleaved_write_frame(ic, &pack);if (ret == 0){//cout << "#" << flush;}
}}
参考文章
ffmpeg官网推流应用
FFMPEG之最简单的RTMP推流代码样例
RTMP、RTSP原理以及GPU使用
知乎ffmpeg代码细节以及其它RTMP开启
ffmpeg引用头文件
FFmpeg 代码实现流媒体推流(RTSP)
命令行推流
常用命令行推流和python模块推流
FFMPEG推相机图片到服务器
代码+ffmpeg命令方式进行推流
FFmpeg 代码转发推流到 rtsp/rtmp
ngix rtmp推流
ffmpeg、FFprobe命令行指南
web服务器(nginx)
https://github.com/arut/nginx-rtmp-module
Output RTSP stream with ffmpeg
fmepg中sws_scale() 函数解析
https://blog.csdn.net/m0_37400316/article/details/107207271
ffmpeg构成
ffmpeg c++代码推流RTSP/RTMP(命令行推流)相关推荐
- PerfLib 2.0 计数器 removal 失败,退出代码为 2。命令行: C:\Windows\system32\unlodctr.exe /m:hkengperfctr.xml
sql server 2019卸载后重装反复出现: PerfLib 2.0 计数器 removal 失败,退出代码为 2.命令行: C:\Windows\system32\unlodctr.exe / ...
- C++ 简化 推箱子 小游戏 完整代码 参考网络资料 命令行运行 仅供初学者参考交流
C++ 简化 推箱子 小游戏 完整代码 参考网络资料 命令行运行 仅供初学者参考交流 说明:学做了4关推箱子, 仅供初学者参考可用g++ 编译,可以将内容复制到TXT文件,将后缀改为".cp ...
- Happytime RTSP Pusher,命令行工具提供
Happytime RTSP Pusher,命令行工具提供 Happytime RTSP Pusher是一款软件应用程序,可用于流式传输各种设备和文件,例如相机和屏幕活动,以及来自本地硬盘的音频和视频 ...
- 不用obs不用直播姬,直接ffmpeg命令行推流RTSP到B站直播间
最近在做公司的直播准备工作,在尝试过程中,发现公司的"海康威视 DS-2CD1021FD-IW1"摄像头输出的是RTSP格式的. 经过各种搜索,尝试了用B站官方直播姬抓VLC窗口, ...
- Windows远程桌面实现之五(FFMPEG实现桌面屏幕RTSP,RTMP推流及本地保存)
by fanxiushu 2018-07-10 转载或引用请注明原始作者. 前面文章分别阐述了,如何抓取电脑屏幕数据,如何采集电脑声音, 如何实现在现代浏览器中通过HTML5和WebSocket直接进 ...
- ffmpeg 推流同时录像命令_ffmpeg推流命令
安悦溪/图片来自网络 一.ffmpeg推流命令 ffmpeg -re -i /Users/WX/Desktop/login_video.mp4 -vcodec libx264 -acodec aac ...
- 【TypeScript】通过node-cmd使用代码,执行cmd命令行
使用第三方库 node-cmd 执行 cmd 命令行命令 具体实现代码如下: const cmdShell = require('node-cmd')async function cmd(domain ...
- python运行代码不成功_命令行执行python模块时提示包找不到的问题
庄稼人不是专职python开发的道友,虽然与python相识已多年,可惜相识不相知,只是偶尔借助pydev写一些简单的小工具. 多年来,一直困惑于这样一个问题:同样的工程,同样的代码,使用pydev可 ...
- linux下使用vlc命令行推流
VLC使用总结 关键字: VLC, streaming server, VOD server, media trascoding, streaming media player, audio broa ...
最新文章
- 4.MySQL连接并选择数据库(SQL C)
- 通过web sql实现增删查改
- h5 rtmp推荐控件_H5播放Rtmp之videojs播放
- java 二维数组倒置_Java数组反转及二维数组
- Java面试题—内部类和静态内部类的区别
- SourceTree查找Github修改记录的技巧
- 风变的python课程怎么样_风的解释|风的意思|汉典“风”字的基本解释
- TCP/ITX协议面试总结
- 2021抖音电商达人生态报告
- 数据传输服务 DTS > 产品简介 > 功能特性 > 数据订阅(新版)
- 对软件测试“核心价值”的思考
- stm32读取驾驶模拟器数据 stm32F407读取joystick数据
- 基于Python操作Excel实战案例
- 基于微信小程序的医疗监督反馈小程序的设计与实现-计算机毕业设计源码+LW文档
- win10计算机设备感叹号,win10网络适配器出现感叹号的解决方法
- “不喝就是不给我面子”,酒局领导逼你喝酒咋办?坚守这条底线
- 基于Java的旅行管理系统的设计与实现
- Windows 11和Windows 2022 TLS/SSL(Schannel SSP)的加密套件
- 还不了解Oauth2协议?这篇文章从入门到入土让你了解Oauth2以及Spring Security OAuth2 的使用
- STM32学习笔记V1.1GPIO寄存器的ODR、BSRR、BRR