FFMPEG API函数根据SDP文件接收RTP媒体流
背景
版本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媒体流相关推荐
- 标准C函数库头文件、POSIX标准库头文件和Windows API函数库头文件说明
1. 标准C函数库头文件 名字 源自 描述 <assert.h> 包含断言宏,被用来在程序的调试版本中帮助检测逻辑错误以及其他类型的bug. <complex.h> C99 一 ...
- C语言rewind()函数(设置文件位置为给定流 stream 的文件的开头)(回到文件开头重读)
C 标准库 - <stdio.h> 文章目录 描述 声明 参数 返回值 实例 描述 C 库函数 void rewind(FILE *stream) 设置文件位置为给定流 stream 的文 ...
- 用API函数播放wav文件声音不连续的解决方法
作为一个多媒体技术方面的初学者,我从wav文件的播放开始了解媒体播放的流程. 于是从建立两个线程开始,线程1用来将文件中的数据读到Buffer中去,以后称为读线程,线程2用来将Buffer中的数据送到 ...
- Windows.h 常用API函数【转】
转自:https://blog.csdn.net/farmwang/article/details/50603608 http://www.vbgood.com/api.html http://hi. ...
- windows常用 API函数
系统API查询 http://www.vbgood.com/api.html http://hi.baidu.com/3582077/item/9cc3483b581f53c5392ffae3 第一个 ...
- windows常用API函数
windows常用API函数 http://www.vbgood.com/api.html http://hi.baidu.com/3582077/item/9cc3483b581f53c5392ff ...
- rtp 多媒体流同步控制 实时传输协议 简介
RTP(Real-time Transport Protocol)是由IETF开发的实时传输协议,可以在面向连接或无连接的下层协议上工作,通常和UDP协议一起使用.RTP的工作机理与RSVP不同,主要 ...
- 【FFmpeg】FFmpeg 相关术语简介 ( 容器 | 媒体流 | 数据帧 | 数据包 | 编解码器 | 复用 | 解复用 )
文章目录 一.FFmpeg 简介 二.FFmpeg 相关术语 1.容器 2.媒体流 3.数据帧 4.数据包 5.编解码器 6.复用 7.解复用 博客资源 一.FFmpeg 简介 FFmpeg 是 &q ...
- 如何发送和接收RTP封包的H264,用FFmpeg解码
这篇文章给大家介绍怎么打包H264分片到RTP包,并且实现一个播放程序演示接收RTP包和用FFmpeg解码.为了让大家更了解H264打包成RTP的细节,有必要罗嗦一下向大家介绍一些相关的基础知识,下面 ...
最新文章
- ASP .NET Core Web MVC系列教程一:创建一个Web应用程序
- Paper:《NÜWA: Visual Synthesis Pre-training for Neural visUal World creAtion,女娲:用于神经视觉世界创造的视觉》翻译与解读
- Memcached学习笔记 — 第四部分:Memcached Java 客户端-gwhalin(1)-介绍及使用
- 前端学习(2963):element-ui介绍
- 【C/C++开发】C++11 并发指南二(std::thread 详解)
- 帝云CMS内容管理系统DiYunCMS v4.3.12
- dijkstra+priority_queue+vector
- Android 获取联系人的公司,android-如何从设备的联系人列表中获取用户...
- Zendframework 模块加载事件触发顺序。
- treeview wpf代码设置选中_C# WPF过渡效果实现(Transitions)
- java开发正则表达式
- ISO27000系列标准
- Golang 协程 跟Java NIO
- search:笔记本插上耳机还是外放?(Dell win10)
- Oracle怎么清除视图数据,Oracle删除视图
- Benchmarking of computational error-correction methods for next-generation sequen下一代测序数据的计算纠错方法的基准测试
- easyui datagrid deleteRow(删除行)的BUG或者updateRow值更新了不展示问题
- 自定义View - 仿QQ运动步数效果
- python往npy写入数据_操作python实现npy格式文件转换为txt文件
- 计算机中的位,字节,字,字长的概念
热门文章
- linux 中yum 安装maven
- 东北大学acm暑期夏令营第八天
- [Halcon资料] 学习资料链接
- Android 如何通过menu id来得到menu item 控件
- Linux 多线程开发(附有案例代码)
- 升级iOS8和iOS9系统后,保险箱Pro、私人保险箱、私密相冊打开就闪退的官方解决方式...
- ANSI C、C89、C99和C51的区别
- 《人人都是项目经理V2.0》读书笔记——第3章 需求管理——筛选干系人的需求
- 第五届“泰迪杯“技能赛赛题讲解直播来啦
- C++个人财务管理系统