当前位置: 首页 > news >正文

C++ ffmpeg RTSP 视频推流实现, arm linux平台

环境:
FFmpeg版本:n4.2.2

下载地址(下载编译后请确认版本正确):

https://ffmpeg.org//download.html
下面地址经过第三方git加速可能存在实效性:
https://hub.fgit.cf/FFmpeg/FFmpeg/tree/n4.4.2

实现代码:


#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
#endif#define CODEC_FLAG_GLOBAL_HEADER  0x00400000int 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  = "test.mp4";//输入URL(Input file URL)out_filename = "rtmp://192.168.110.79:1935/live/1";//输出 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 |= 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;
}

cmake:

cmake_minimum_required(VERSION 3.10.2)
project(w_test)SET(CMAKE_C_COMPILER /mnt/sda2/rk3588_sdk/other/rk3566_gcc_tool/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc)
SET(CMAKE_CXX_COMPILER /mnt/sda2/rk3588_sdk/other/rk3566_gcc_tool/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-g++)
SET(CMAKE_STRIP /mnt/sda2/rk3588_sdk/other/rk3566_gcc_tool/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-strip)set(ffmpeg_libs_DIR /home/rog/my_file/other_LIB/myffmpeg/4.2.2/FFmpeg/my_lib_arm/lib)
set(ffmpeg_headers_DIR /home/rog/my_file/other_LIB/myffmpeg/4.2.2/FFmpeg/my_lib_arm/include)add_library( avcodec SHARED IMPORTED)
add_library( avfilter SHARED IMPORTED )
add_library( swresample SHARED IMPORTED )
add_library( swscale SHARED IMPORTED )
add_library( avformat SHARED IMPORTED )
add_library( avutil SHARED IMPORTED )set_target_properties( avcodec PROPERTIES IMPORTED_LOCATION ${ffmpeg_libs_DIR}/libavcodec.so )
set_target_properties( avfilter PROPERTIES IMPORTED_LOCATION ${ffmpeg_libs_DIR}/libavfilter.so )
set_target_properties( swresample PROPERTIES IMPORTED_LOCATION ${ffmpeg_libs_DIR}/libswresample.so )
set_target_properties( swscale PROPERTIES IMPORTED_LOCATION ${ffmpeg_libs_DIR}/libswscale.so )
set_target_properties( avformat PROPERTIES IMPORTED_LOCATION ${ffmpeg_libs_DIR}/libavformat.so )
set_target_properties( avutil PROPERTIES IMPORTED_LOCATION ${ffmpeg_libs_DIR}/libavutil.so )include_directories( ${ffmpeg_headers_DIR} )
link_directories(${ffmpeg_libs_DIR} )set(CMAKE_CXX_STANDARD 14)
add_executable(w_test main.cpp)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} avcodec avformat avutil swresample swscale swscale avfilter )

效果:
在这里插入图片描述
参考:
最简单的基于FFmpeg的推流器(以推送RTMP为例)

ffmpeg c++代码推流RTSP/RTMP(命令行推流)

相关文章:

  • GitHub国内打不开(解决办法有效)
  • 第5章 python深度学习——波斯美女
  • Django入门,十分钟学会登录网页
  • JSP仓储管理系统myeclipse定制开发SQLServer数据库网页模式java编程jdbc
  • 将多个excel文件中的特定数据汇总到一个excel中
  • SpringBoot中阿里云OSS的使用
  • MCU启动文件小解一下
  • chromedriver安装和环境变量配置
  • 2023美赛A题之Lotka-Volterra【完整思路+代码】
  • C#,欧拉数(Eulerian Number)的算法与源代码
  • 系统架构设计师-22年-下午题目
  • JVM篇----第十七篇
  • iOS17使用safari调试wkwebview
  • 中国的茶文化:历史、传统与生活
  • js实现动漫拼图2.0版
  • 2018一半小结一波
  • C++类的相互关联
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • gulp 教程
  • Terraform入门 - 3. 变更基础设施
  • Tornado学习笔记(1)
  • Vue.js源码(2):初探List Rendering
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • Windows Containers 大冒险: 容器网络
  • 干货 | 以太坊Mist负责人教你建立无服务器应用
  • 工程优化暨babel升级小记
  • 前言-如何学习区块链
  • 协程
  • 一个JAVA程序员成长之路分享
  • 在electron中实现跨域请求,无需更改服务器端设置
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • 通过调用文摘列表API获取文摘
  • ​【数据结构与算法】冒泡排序:简单易懂的排序算法解析
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • #每日一题合集#牛客JZ23-JZ33
  • (07)Hive——窗口函数详解
  • (delphi11最新学习资料) Object Pascal 学习笔记---第13章第6节 (嵌套的Finally代码块)
  • (LeetCode 49)Anagrams
  • (安卓)跳转应用市场APP详情页的方式
  • (搬运以学习)flask 上下文的实现
  • (笔试题)合法字符串
  • (三)终结任务
  • (三分钟)速览传统边缘检测算子
  • (转载)CentOS查看系统信息|CentOS查看命令
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .net core 6 集成和使用 mongodb
  • .Net Core和.Net Standard直观理解
  • .NET Core跨平台微服务学习资源
  • .net FrameWork简介,数组,枚举
  • .Net Winform开发笔记(一)
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .NET技术成长路线架构图
  • .NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth
  • .NET上SQLite的连接