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

前言

  • 上一篇文章我们介绍了如何使用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,实现推流,内容如下
c 复制代码
  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文件,实现编译,内容如下
sh 复制代码
  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工具来播放推送流
相关推荐
你喜欢喝可乐吗?14 小时前
windows 使用 FFmpeg 放大视频原声
windows·音视频·开源软件
那就举个栗子!1 天前
自主采集高质量三维重建数据集指南:面向3DGS与NeRF的图像与视频拍摄技巧【2025最新版!!】
3d·音视频
18538162800余--1 天前
短视频矩阵系统贴牌开发实战:批量剪辑文件夹功能设计与实现
线性代数·矩阵·音视频
随风LL1 天前
AE模板 动感节奏快闪图文展示介绍片头 Typographic Intro
音视频
南客先生1 天前
音视频项目在微服务领域的趋势场景题深度解析
java·微服务·面试·性能优化·音视频·高并发
EasyGBS1 天前
哪些因素会影响远程视频监控的质量?浅述EasyCVR视频智能诊断技术
大数据·网络·人工智能·音视频
西楚曹长卿2 天前
RN 获取视频封面,获取视频第一帧
android·react native·音视频·react
EasyDSS2 天前
基于WebRTC技术,EasyRTC音视频实时通话助力全网会议的智能化转型
网络·音视频
小咖自动剪辑2 天前
海外平台短剧批量混剪自动剪辑智能去重与多语言适配方案解析
音视频·语音识别·实时音视频·视频编解码
说码解字2 天前
如何系统学习音视频
学习·音视频