背景

版本ffmpeg 3.3.3;使用 FFmpeg实时接收rtp 音频和视频流,并生成视频文件。

在网上查阅了大量资料,基本上都是使用命令行来接收rtp媒体流的,由于项目中不得不使用ffmpeg接收RTP实时流。因此花了不少时间研究。

ffmepg 默认是不打开rtp协议的,需要添加白名单后,并根据sdp文件来接收rtp媒体流。sdp文件也很费劲,刚开始不明白sdp文件是啥,具体含义也不知道,研究半天才搞懂大概。

添加白名单时一定要申请单独的内存块,我在这个坑里痛苦了很久,之前直接赋值,老是崩溃,不明原因。后来经高人指点,幡然醒悟,白名单在avformat_close_input中会进行free,必须要申请内存才行。

废话不多说,直接上代码

    //初始化输入上下文    AVFormatContext    *p_ifmt_ctx_v = avformat_alloc_context();AVFormatContext       *p_ifmt_ctx_a  = avformat_alloc_context();AVInputFormat        *p_ifmt_v = NULL;AVInputFormat         *p_ifmt_a = NULL;eU8                   buffer[1280] = {0};eU8                 port_v[10] = {0};eU8                   port_a[10] = {0};eU8                   sdp_file_name[128] = {0};eU8                   sdp_file_name_a[128] = {0};FILE                *fp = NULL;p_ifmt_ctx_v ->flags |= AVFMT_NOFILE;//添加白名单,这里很重要,如果不申请内存,在avformat_close_input中会宕p_ifmt_ctx_v ->protocol_whitelist = av_malloc(sizeof("file,udp,rtp"));memcpy(p_ifmt_ctx_v ->protocol_whitelist,"file,udp,rtp",sizeof("file,udp,rtp"));p_ifmt_ctx_a ->flags |= AVFMT_NOFILE;//添加白名单,这里很重要,如果不申请内存,在avformat_close_input中会宕p_ifmt_ctx_a ->protocol_whitelist = av_malloc(sizeof("file,udp,rtp"));memcpy(p_ifmt_ctx_a ->protocol_whitelist,"file,udp,rtp",sizeof("file,udp,rtp"));//输入的文件格式为sdpp_ifmt_v = av_find_input_format("sdp");p_ifmt_a = av_find_input_format("sdp");av_register_all();avfilter_register_all();avformat_network_init(); //生成sdp文件,ffmpeg根据sdp文件获取到ip地址和port,以及媒体格式信息sprintf(sdp_file_name, "%d", threadid);strcat(sdp_file_name,"-v");strcat(sdp_file_name,".sdp");fp = fopen(sdp_file_name,"wb+");if(fp ==NULL){printf("cannot open file sdp_file_name=%s \n",sdp_file_name);return FAILURE;}sprintf(port_v,"%d",video_port);strcat(buffer,"v=0\r\n");//发送rtp流的源ip地址   strcat(buffer,"o=- 0 0 IN IP4 127.0.0.1\r\n");strcat(buffer,"s=video\r\n" );//接收rtp流的ip地址strcat(buffer,"c=IN IP4 127.0.0.1\r\n" );strcat(buffer,"t=0 0\r\n" );strcat(buffer,"a=tool:libavformat 57.71.100\r\n");strcat(buffer,"m=video ");strcat(buffer,"  ");// 接收rtp流的端口strcat(buffer,port_v);//98 代表的是媒体格式,即rtp头中携带的媒体格式,我这里的h264 格式类型为98strcat(buffer," RTP/AVP 98\r\n");strcat(buffer,"a=rtpmap:98 H264/90000\r\n");fprintf(fp,"%s\n",buffer);fclose(fp);if ((ret = avformat_open_input(&p_ifmt_ctx_v , sdp_file_name, p_ifmt_v , NULL)) != 0) {printf( "Cannot open p_ifmt_ctx_v file %s\n",buffer);return -1;}
//收音频流的sdp文件memset(sdp_file_name_a,0,sizeof(sdp_file_name_a));memset(buffer,0,sizeof(buffer));sprintf(sdp_file_name_a, "%d", threadid);strcat(sdp_file_name_a,"-a");strcat(sdp_file_name_a,".sdp");fp = fopen(sdp_file_name_a,"wb+");if(fp ==NULL){printf("cannot open file sdp_file_name_a=%s \n",sdp_file_name_a);return -1;}sprintf(port_a,"%d",audio_port);strcat(buffer,"v=0\r\n");    strcat(buffer,"o=- 0 0 IN IP4 127.0.0.1\r\n");strcat(buffer,"s=audio \r\n" );strcat(buffer,"c=IN IP4 127.0.0.1\r\n" );strcat(buffer,"t=0 0\r\n" );strcat(buffer,"a=tool:libavformat 57.71.100\r\n");strcat(buffer,"m=audio ");strcat(buffer,"  ");strcat(buffer,port_a);//这里是amr格式类型,rtp头中显示126,根据实际进行修改strcat(buffer," RTP/AVP 126\r\n");strcat(buffer,"a=rtpmap:126 AMR/8000/1\r\n");fprintf(fp,"%s\n",buffer);fclose(fp);if ((ret = avformat_open_input(&p_ifmt_ctx_a  , sdp_file_name_a, p_ifmt_a , NULL)) != 0) {printf( "Cannot open p_ifmt_ctx_a  file %s\n",in_filename_a);return -1;}

这里就打开了端口开始接收rtp媒体流了,接下来打印一下媒体流的信息,代码如下:

    if ((ret = avformat_find_stream_info(p_ifmt_ctx_v, NULL)) < 0) {printf( "Cannot find ifmt_ctx_v stream information\n");goto end;} if ((ret = avformat_find_stream_info(p_ifmt_ctx_a, NULL)) < 0) {printf( "Cannot find ifmt_ctx_a stream information\n");goto end;}printf("===========Input Information================\n");av_dump_format(ifmt_ctx_a, 0, in_filename_a, 0);av_dump_format(ifmt_ctx_v, 0, in_filename_v, 0);    printf("============================================\n");

至此,ffmpeg根据sdp文件来接收rtp媒体流完成,在此记录一下。

参考 ffmpeg监听和接收rtp音视频流_阳光的威威的博客-CSDN博客_ffmpeg 监听

FFMPEG API函数根据SDP文件接收RTP媒体流相关推荐

  1. 标准C函数库头文件、POSIX标准库头文件和Windows API函数库头文件说明

    1. 标准C函数库头文件 名字 源自 描述 <assert.h> 包含断言宏,被用来在程序的调试版本中帮助检测逻辑错误以及其他类型的bug. <complex.h> C99 一 ...

  2. C语言rewind()函数(设置文件位置为给定流 stream 的文件的开头)(回到文件开头重读)

    C 标准库 - <stdio.h> 文章目录 描述 声明 参数 返回值 实例 描述 C 库函数 void rewind(FILE *stream) 设置文件位置为给定流 stream 的文 ...

  3. 用API函数播放wav文件声音不连续的解决方法

    作为一个多媒体技术方面的初学者,我从wav文件的播放开始了解媒体播放的流程. 于是从建立两个线程开始,线程1用来将文件中的数据读到Buffer中去,以后称为读线程,线程2用来将Buffer中的数据送到 ...

  4. Windows.h 常用API函数【转】

    转自:https://blog.csdn.net/farmwang/article/details/50603608 http://www.vbgood.com/api.html http://hi. ...

  5. windows常用 API函数

    系统API查询 http://www.vbgood.com/api.html http://hi.baidu.com/3582077/item/9cc3483b581f53c5392ffae3 第一个 ...

  6. windows常用API函数

    windows常用API函数 http://www.vbgood.com/api.html http://hi.baidu.com/3582077/item/9cc3483b581f53c5392ff ...

  7. rtp 多媒体流同步控制 实时传输协议 简介

    RTP(Real-time Transport Protocol)是由IETF开发的实时传输协议,可以在面向连接或无连接的下层协议上工作,通常和UDP协议一起使用.RTP的工作机理与RSVP不同,主要 ...

  8. 【FFmpeg】FFmpeg 相关术语简介 ( 容器 | 媒体流 | 数据帧 | 数据包 | 编解码器 | 复用 | 解复用 )

    文章目录 一.FFmpeg 简介 二.FFmpeg 相关术语 1.容器 2.媒体流 3.数据帧 4.数据包 5.编解码器 6.复用 7.解复用 博客资源 一.FFmpeg 简介 FFmpeg 是 &q ...

  9. 如何发送和接收RTP封包的H264,用FFmpeg解码

    这篇文章给大家介绍怎么打包H264分片到RTP包,并且实现一个播放程序演示接收RTP包和用FFmpeg解码.为了让大家更了解H264打包成RTP的细节,有必要罗嗦一下向大家介绍一些相关的基础知识,下面 ...

最新文章

  1. ASP .NET Core Web MVC系列教程一:创建一个Web应用程序
  2. Paper:《NÜWA: Visual Synthesis Pre-training for Neural visUal World creAtion,女娲:用于神经视觉世界创造的视觉》翻译与解读
  3. Memcached学习笔记 — 第四部分:Memcached Java 客户端-gwhalin(1)-介绍及使用
  4. 前端学习(2963):element-ui介绍
  5. 【C/C++开发】C++11 并发指南二(std::thread 详解)
  6. 帝云CMS内容管理系统DiYunCMS v4.3.12
  7. dijkstra+priority_queue+vector
  8. Android 获取联系人的公司,android-如何从设备的联系人列表中获取用户...
  9. Zendframework 模块加载事件触发顺序。
  10. treeview wpf代码设置选中_C# WPF过渡效果实现(Transitions)
  11. java开发正则表达式
  12. ISO27000系列标准
  13. Golang 协程 跟Java NIO
  14. search:笔记本插上耳机还是外放?(Dell win10)
  15. Oracle怎么清除视图数据,Oracle删除视图
  16. Benchmarking of computational error-correction methods for next-generation sequen下一代测序数据的计算纠错方法的基准测试
  17. easyui datagrid deleteRow(删除行)的BUG或者updateRow值更新了不展示问题
  18. 自定义View - 仿QQ运动步数效果
  19. python往npy写入数据_操作python实现npy格式文件转换为txt文件
  20. 计算机中的位,字节,字,字长的概念

热门文章

  1. linux 中yum 安装maven
  2. 东北大学acm暑期夏令营第八天
  3. [Halcon资料] 学习资料链接
  4. Android 如何通过menu id来得到menu item 控件
  5. Linux 多线程开发(附有案例代码)
  6. 升级iOS8和iOS9系统后,保险箱Pro、私人保险箱、私密相冊打开就闪退的官方解决方式...
  7. ANSI C、C89、C99和C51的区别
  8. 《人人都是项目经理V2.0》读书笔记——第3章 需求管理——筛选干系人的需求
  9. 第五届“泰迪杯“技能赛赛题讲解直播来啦
  10. C++个人财务管理系统