音视频(二)之使用FFMpegSDK在我们自己的代码中进行推流

news2024/9/22 4:19:37

前言

  • 上一篇文章我们介绍了如何使用FFMpeg工具进行推流。但如果要在我们的代码工程中,实现推流。就要下载FFMpegSDK包,调用相关API,在我们自己的程序中实现推流。

FFMpegSDK下载

  • 下载动态库文件
    在这里插入图片描述
  • 选择这个下载
    在这里插入图片描述

使用FFMpegSDK推流

  • 下载FFMpegSDK后,拷贝到我们的工程下
  • 目录结构如下
  •   ├─ bin
      ├─ doc
      ├─ include
      		├─ libavcodec
      		├─ libavdevice
      		├─ libavfilter
      		├─ libavformat
      		├─ libavutil
      		├─ libpostproc
      		├─ libswresample
      		└─ libswscale
      ├─ lib
      		└─pkgconfig
      ├─ src
      		└─ main.cpp
      ├─ build_x64
      └─ CMakeLists.txt
    
  • bin,doc,include,lib目录都是FFMpegSDK包中的内容,直接拷贝过来
  • src 在这个目录下创建一个源文件 main.cpp,在代码中调用FFMpeg提供的API,实现推流,内容如下
  •   extern "C"{
      #include "libavformat/avformat.h"
      #include "libavcodec/avcodec.h"
      #include "libavutil/time.h"
      };
      #include <iostream>
      
      
      void printErr(int errNum);
      
      static double r2d(AVRational r){
          return (r.num == 0 || r.den == 0) ? 0.0 : (double)r.num / (double)r.den;
      }
      
      int main(){
          //初始化网络库以及网络加密协议相关的库
          avformat_network_init();
      
          //打开文件, 解封文件头
          AVFormatContext *inContext = NULL;
          char *inFile = "001.mp4";
          int ret = avformat_open_input(&inContext, inFile, 0, 0);
          if(ret != 0){
              printErr(ret);
              return -1;
          }
      
          std::cout<<"avformat_open_input success"<<std::endl;
      
          //获取音视频流信息
          ret = avformat_find_stream_info(inContext, 0);
          if(ret != 0){
              printErr(ret);
              return -1;
          }
      
          std::cout<<"avformat_find_stream_info success"<<std::endl;
      
          //打印信息
          av_dump_format(inContext, 0, inFile, 0);
      
          //输出流
          AVFormatContext *outContext;
          char *outFile = "rtmp://192.168.206.131:10088/live";
          ret = avformat_alloc_output_context2(&outContext, 0, "flv", outFile);
          if(outContext == 0){
              printErr(ret);
              return -1;
          }
      
          std::cout<<"avformat_alloc_output_context2 success"<<std::endl;
      
          //配置输出流
          //遍历输入的AVStream
          for(int i = 0; i < inContext->nb_streams; i++){
              AVStream *outStream = avformat_new_stream(outContext, NULL);
              if(outStream == NULL){
                  printErr(-1);
                  return -1;
              }
      
              //复制配置信息
              ret = avcodec_parameters_copy(outStream->codecpar, inContext->streams[i]->codecpar);
              if(ret < 0){
                  printErr(ret);
                  return -1;
              }
      
              outStream->codecpar->codec_tag = 0;
          }
      
          //输出
          av_dump_format(outContext, 0, outFile, 1);
      
          //rtmp推流
          
          //打开io
          ret = avio_open(&outContext->pb, outFile, AVIO_FLAG_WRITE);
          if(ret != 0){
              printErr(ret);
              return -1;
          }
          std::cout<<"avio_open success"<<std::endl;
      
          //写入头信息
          ret = avformat_write_header(outContext, NULL);
          if(ret < 0){
              printErr(ret);
              return -1;
          }
          std::cout<<"avformat_write_header success"<<std::endl;
      
          //推流帧数据
          AVPacket avpkt;
          long long startTime = av_gettime();
          while(1){
              //读帧数据
              ret = av_read_frame(inContext, &avpkt);
              if(ret != 0){
                  break;
              }
      
              std::cout << avpkt.pts << std::endl;
      
              //计算转换pts dts
              AVRational inTime = inContext->streams[avpkt.stream_index]->time_base;
              AVRational outTime = outContext->streams[avpkt.stream_index]->time_base;
              avpkt.pts = av_rescale_q_rnd(avpkt.pts, inTime, outTime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
              avpkt.dts = av_rescale_q_rnd(avpkt.dts, inTime, outTime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
              avpkt.duration = av_rescale_q_rnd(avpkt.duration, inTime, outTime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
              avpkt.pos = -1;
      
               //处理视频帧,控制推流速度
              if(inContext->streams[avpkt.stream_index]->codecpar->codec_type = AVMEDIA_TYPE_VIDEO){
                  //时间基数
                  AVRational tb = inContext->streams[avpkt.stream_index]->time_base;
                  
                  long long nowTime = av_gettime() - startTime;
                  long long dtsTime = avpkt.dts * (1000 * 1000 * r2d(tb));
                  if(dtsTime > nowTime){
                      av_usleep(dtsTime - nowTime);
                  }
                  
              }
      
      
              //发送数据
              ret = av_interleaved_write_frame(outContext, &avpkt);
              if(ret < 0){
                  printErr(ret);
                  return -1;
              }
      
              //释放
              av_packet_unref(&avpkt);
          }
      
          system("pause");
          return 0;
      }
      
      void printErr(int errNum){
          char errBuf[1024] = {0};
          av_strerror(errNum, errBuf, sizeof(errBuf));
          system("pause");
      }
    
  • CMakeLists.txt文件,实现编译,内容如下
  •   cmake_minimum_required (VERSION 3.5)
      project (FFmpegSDK)
      
      MESSAGE(STATUS "PROJECT_SOURCE_DIR" ${PROJECT_SOURCE_DIR})
      SET(SRC_LISTS ${PROJECT_SOURCE_DIR}/src/main.cpp)
         
      
      # 配置工程需要的头文件目录 
      include_directories(${PROJECT_SOURCE_DIR}/include)
      
      
      IF(WIN32)
      	set(CMAKE_C_FLAGS_RELEASE "/MD /MP /Od /Zi /EHsc")
      ENDIF()
      
      
      set(PRO_AVCODEC_LIB ${PROJECT_SOURCE_DIR}/lib/avcodec.lib)
      set(PRO_AVFORMAT_LIB ${PROJECT_SOURCE_DIR}/lib/avformat.lib)
      set(PRO_AVUTIL_LIB ${PROJECT_SOURCE_DIR}/lib/avutil.lib)
      
      
      ADD_EXECUTABLE(FFmpegSDK ${SRC_LISTS})
      TARGET_LINK_LIBRARIES(FFmpegSDK ${PRO_AVCODEC_LIB} ${PRO_AVFORMAT_LIB} ${PRO_AVUTIL_LIB})
    
  • 在build_x64目录下执行以下编译命令
    • cmake -G “Visual Studio 14 2015 Win64” …
    • cmake --build ./ --config Release
  • 编译成功后,在build_x86\Release目录下就会生成可执行程序FFmpegSDK.exe
  • 再把对应的库avcodec-60.dll、avformat-60.dll、avutil-58.dll、swresample-4.dll和要推送的视频文件001.mp4拷贝到build_x86\Release下。运行FFmpegSDK.exe就可以实现推流
  • 可以使用VLC工具来播放推送流
    在这里插入图片描述

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

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

相关文章

jacob朗读中文,jacob生成中文语音音频文件,以生成MP3文件为例,不需要配置DLL

前言 本文使用jacob朗读文字和生成中文语音音频文件功能,与不同的是,本文不需要配置DLL到JVM根目录,只需要从项目类路径加载DLL即可。 jacob介绍 Jacob 是一个 Java 库,允许 Java 应用程序与Microsoft Windows DLL 或 COM 库进行通信。它通过使用自定义DLL来实现这一点,…

docker镜像仓库

Hlarbor harbor是一个开源的云原生镜像仓库&#xff0c; 它允许仓库用户存储&#xff0c;使用docker镜像。可以将harbor看做是私有的dockerhub&#xff0c;它提供了更新安全性和控制性&#xff0c; 让组织能够安全的存储和管理镜像。 harbor RBAC&#xff1a;基于角色访问控制…

ImportError: DLL load failed: 找不到指定的模块。解决方法 from ._nnls import nnls 报错

实验时遇到过如下错误 ImportError: DLL load failed: 找不到指定的模块。 往前查看错误位置发现如下错误 from ._nnls import nnls 或者 from scipy import special, optimize, from ._nnls import nnls 解决方法&#xff1a; 依次执行下述命令 conda remove --force numpy …

[大三上]区块链和分布式计算

[大三上]区块链和分布式计算 区块链中的分布式系统: 分布式最大的应用: 区块链, 分布式系统是区块链的一个基础 分布式计算: 分布式计算&#xff08;Distributed Computing&#xff09;&#xff1a;指将一个计算任务分解成多个子任务&#xff0c;分配给不同的计算节点&#…

项目管理-2023西电网课课后习题答案-第三章

文章目录 第三章答案1-1011-2021-3031-4041-5051-6061-7071-80 [✅] 第一章答案[✅] 第二章答案[✅] 第三章答案[✅] 第四章答案 第五章答案 第三章答案 1-10 11-20 21-30 31-40 41-50 51-60 61-70 71-80

VSCode 自动修改闭合标签

1.打开应用商店&#xff0c;搜索 auto rename tag &#xff0c;选择第一个&#xff0c;点击安装。 2.安装完毕后随便打开一个 HTML 文件&#xff0c;当我们修改起始标签时&#xff0c;闭合标签也会自动更改。 原创作者&#xff1a;吴小糖 创建时间&#xff1a;2023.10.25

高德 几千条数据,点标记Marker转海量标注 LabelMarker

** 高德地图说&#xff1a; 当需要在地图添加千级以上的点标记时&#xff0c;LabelMarker 是代替 Marker 的更好选择。 ** 如图&#xff0c;当数据量超过两千时&#xff0c;如果我们使用的是Marker点标记&#xff0c;页面将会非常的卡&#xff0c;卡顿很久都不出现标记点。因此…

NFS网盘挂载-Ubuntu(linux)

我有2台机器&#xff0c;我想把A机器挂载到B机器上。 NFS安装 B机器执行-服务端&#xff1a;sudo apt-get install nfs-kernel-server A机器执行-客户端&#xff1a;sudo apt-get install nfs-common 指定共享盘 进入B机器&#xff0c;配置共享盘 创建需要让别人访问的目录…

Pytorch:model.train()和model.eval()用法和区别,以及model.eval()和torch.no_grad()的区别

1 model.train() 和 model.eval()用法和区别 1.1 model.train() model.train()的作用是启用 Batch Normalization 和 Dropout。 如果模型中有BN层(Batch Normalization&#xff09;和Dropout&#xff0c;需要在训练时添加model.train()。model.train()是保证BN层能够用到每一…

时尚女童卫衣—Get麻麻同款和宝贝一起穿

分享女儿的时尚穿搭—卫衣 不知道各位姐妹那边的天气如何 我们这边现在穿卫衣刚刚好 这件卫衣百搭圆领&#xff0c;经典的额版哦 加绒卫衣特别保暖 卡通鹅的图案宝贝特别喜欢 和宝贝一起穿亲子装真的很幸福&#xff01;

记录一次“超出内存限制”的原因

问题&#xff1a; 问题的来源是力扣的这一条题目&#xff1a;LCR 048. 二叉树的序列化与反序列化 - 力扣&#xff08;LeetCode&#xff09; 我寻思着也没啥,就前序遍历呗&#xff0c;时间和空间复杂度都是O(n)&#xff0c;应该能把题目K掉。 问题代码&#xff1a; /*** Defini…

InCopy 2024 v19.0.0.151(文案撰写与编辑软件)

InCopy 2024 for Mac是一款文案撰写与编辑软件&#xff0c;适用于在Mac上进行文字编辑和排版工作。它是Adobe Creative Cloud套件中的一部分&#xff0c;主要面向文字编辑人员、作家和出版团队&#xff0c;提供了一系列强大的功能&#xff0c;以协同工作和改进工作流程。 InCo…

学校巡课工具,这次真包教包会!

随着教育领域的不断发展和科技的快速进步&#xff0c;在线巡课系统已经成为一种强大的工具&#xff0c;为学校、教育机构和教育者提供了全新的教学监督和评估方式。 客户案例 中学巡课项目 成都某中学面临着监督和改进教学质量的挑战。泛地缘科技推出的在线巡课系统&#xff0c…

欧拉图相关的生成与计数问题探究

最近学了一波国家集训队2018论文的最后一个专题。顺便带上了一些我的注解。 先放一波这个论文 1.基本概念 欧拉图问题是图论中的一类特殊的问题。在本文的介绍过程中&#xff0c;我们将会使用一些图 论术语。为了使本文叙述准确&#xff0c;本节将给出一些术语的定义。 定义…

嵌入式软件找实习需要掌握哪些知识?

嵌入式软件找实习需要掌握哪些知识&#xff1f; 嵌入式软件实习暂时不用刷力扣。具体需要掌握哪些知识每个公司的要求都不太一样&#xff0c;因为嵌入式也有很多细分领域&#xff0c;单片机、C语言是需要熟悉的&#xff0c;最近很多小伙伴找我&#xff0c;说想要一些嵌入式资料…

基于springboot实现篮球论坛管理系统项目【项目源码+论文说明】

基于springboot实现篮球论坛管理系统演示 摘要 首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗…

前端应用发布到nodejs server后浏览器刷新404问题

现象&#xff1a;Angular、Vue和React项目SPA应用如果路由模式为history&#xff0c;部署到服务器后&#xff0c;点击浏览器刷新按钮会出现404。 原因&#xff1a;当路由模式为history的时候&#xff0c;服务器端会根据浏览器中的请求地址去匹配资源&#xff0c;此时服务器端没…

安卓恶意应用识别(四)(特征处理与分类模型构建)——终结

前言 前面三章将数据初步整理出来&#xff1a; 1.安卓恶意应用识别&#xff08;一&#xff09;&#xff08;Python批量爬取下载安卓应用&#xff09; 2.安卓恶意应用识别&#xff08;二&#xff09;&#xff08;安卓APK反编译&#xff09; 3.安卓恶意应用识别&#xff08;三&a…

一张Lambda大数据架构架构图

架构图 大数据的架构包括了Lambda架构和Kappa架构&#xff0c;Lambda架构分解为三层&#xff1a;即批处理层、加速层和服务层&#xff1b;Kappa架构不同于Lambda同时计算流计算和批计算并合并视图&#xff0c;Kappa只会通过流计算一条的数据链路计算并产生视图。 该系统的大数…

1024程序员节|是时候,展示真正的实力了!

“代码改变世界&#xff0c;开源创造未来” 一年一度的程序员节如期而至&#xff01; 在由“0”和“1”构建的二进制世界里 运行程序的硬件进制基础是“1024” 因此&#xff0c;将每一年的10月24日定为“程序员节” 而作为码出每一个1024的程序员 则是这个“二进制世界”里…