RTP的接收程序分析_rtp_session_set_jitter_compensation-程序员宅基地

技术标签: 流媒体  学习方法  接收  RTP  

//          程序名:rtprecv.c

//          类型:学习笔记

#include <ortp/ortp.h>

#include <signal.h>
#include <stdlib.h>
#ifndef _WIN32
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#endif
int cond=1;    //变量cond控制着while循环。
void stop_handler(int signum)
{
cond=0;
}
void ssrc_cb(RtpSession *session)    //SSRC环境变量改变时调用此函数。
{
printf("hey, the ssrc has changed !\n");
}
  //输入9个参数
static char *help="usage: rtprecv  filename loc_port [--format format] [--soundcard] [--noadapt] [--with-jitter <milliseconds>]\n";
#define MULAW 0   
#define ALAW 1
#if defined(__hpux) && HAVE_SYS_AUDIO_H   //如果不适用音频设备。则if 与 else之间的函数可删!
#include <sys/audio.h>
int sound_init(int format)
{
int fd;
fd=open("/dev/audio",O_WRONLY);
if (fd<0){
perror("Can't open /dev/audio");
return -1;
}
ioctl(fd,AUDIO_RESET,0);
ioctl(fd,AUDIO_SET_SAMPLE_RATE,8000);
ioctl(fd,AUDIO_SET_CHANNELS,1);
if (format==MULAW)
ioctl(fd,AUDIO_SET_DATA_FORMAT,AUDIO_FORMAT_ULAW);
else ioctl(fd,AUDIO_SET_DATA_FORMAT,AUDIO_FORMAT_ALAW);
return fd;
}
#else
int sound_init(int format)          //没有音频设备时,执行此函数。
{
return -1;
}
#endif
int main(int argc, char*argv[])
{
RtpSession *session;
unsigned char buffer[160];
int err;
uint32_t ts=0;
int stream_received=0;
FILE *outfile;
int local_port;
int have_more; 
int i;
int format=0;       //待删
int soundcard=0;    //待删
int sound_fd=0;     //待删
int jittcomp=40;
bool_t adapt=TRUE;

/* init the lib */
if (argc<3){
printf("%s",help);
return -1;
}
local_port=atoi(argv[2]);    //设置端口
if (local_port<=0) {
printf("%s",help);
return -1;
}
for (i=3;i<argc;i++)      //本程序段总共设置
{
if (strcmp(argv[i],"--noadapt")==0) adapt=FALSE;
if (strcmp(argv[i],"--format")==0){           //音频相关,待删
i++;
if (i<argc){
if (strcmp(argv[i],"mulaw")==0){
format=MULAW;
}else
if (strcmp(argv[i],"alaw")==0){
format=ALAW;
}else{
printf("Unsupported format %s\n",argv[i]);
return -1;
}
}
}
else if (strcmp(argv[i],"--soundcard")==0){    //音频相关,待删
soundcard=1;
}
else if (strcmp(argv[i],"--with-jitter")==0){  
i++;
if (i<argc){
jittcomp=atoi(argv[i]);
printf("Using a jitter buffer of %i milliseconds.\n",jittcomp);
}
}
}
outfile=fopen(argv[1],"wb");
if (outfile==NULL) {
perror("Cannot open file for writing");
return -1;
}
if (soundcard){         //音频相关,待删
sound_fd=sound_init(format);
}
ortp_init();   
ortp_scheduler_init(); 
ortp_set_log_level_mask(ORTP_DEBUG|ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR);
signal(SIGINT,stop_handler);   //设置信号的处理函数
session=rtp_session_new(RTP_SESSION_RECVONLY);
rtp_session_set_scheduling_mode(session,1);  
//设置会话的调度模式。当第二个参数为真时,标示会话可以使用调度模式,例如:阻塞模式。
rtp_session_set_blocking_mode(session,1);
//当第二个参数为真,则使能调度模式。直接影响函数rtp_session_recv_with_ts()与rtp_session_send_with_ts()的行为!
rtp_session_set_local_addr(session,"0.0.0.0",atoi(argv[2]),-1);
//设置本地网络地址,端口号。
rtp_session_set_connected_mode(session,TRUE);
一个connect()在第一个数据包接收后将对源地址进行使用。
//连接一个socket会造成拒绝所有不是connect()里指定的地址发来的数据。
rtp_session_set_symmetric_rtp(session,TRUE);
//穿越防火墙
rtp_session_enable_adaptive_jitter_compensation(session,adapt);
//自适应补偿功能
rtp_session_set_jitter_compensation(session,jittcomp);
//设置补偿时间
rtp_session_set_payload_type(session,0);
//设置负载的类型。H.264的类型为:payload_type_h264
rtp_session_signal_connect(session,"ssrc_changed",(RtpCallback)ssrc_cb,0);
rtp_session_signal_connect(session,"ssrc_changed",(RtpCallback)rtp_session_reset,0);
//有指定的信号出现时,将调用执行函数。同一个信号可定义多个执行函数。
//第四个参数为执行函数的参数。
while(cond)
{
have_more=1;
while (have_more){
err=rtp_session_recv_with_ts(session,buffer,160,ts,&have_more); 
//have_more标识缓冲区是否还有数据没有接收。当用户缓冲区不够大,数据为读取完时,
//则标识have_more指向的数据为1,希望用户再次调用本函数。
if (err>0) stream_received=1;
/* this is to avoid to write to disk some silence before the first RTP packet is returned*/
if ((stream_received) && (err>0)) {
size_t ret = fwrite(buffer,1,err,outfile);   //从缓冲区写入到输出文件!
if (sound_fd>0){        //if函数为向声音设备传送文件,待删除!!!
ret = write(sound_fd,buffer,err);
if (ret==-1){
fprintf(stderr,"write to sound card failed (%s)",strerror(errno));
}
}
}
}
ts+=160;
//ortp_message("Receiving packet.");
}
rtp_session_destroy(session);
ortp_exit();
ortp_global_stats_display();
return 0;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qinjinghua2012/article/details/45225657

智能推荐

OSG for Android实现VPB地形,倾斜影像与三维模型加载_android 加载倾斜模型-程序员宅基地

文章浏览阅读1k次。案例1.加载VPB地形数据案例2.加载倾斜影像数据案例3.加载三维模型数据_android 加载倾斜模型

2.10 UITapGestureRecognizer手势之单击 [原创iOS开发-Xcode教程]_ios开发中,uitap的点击区域-程序员宅基地

文章浏览阅读603次。1. 在欢迎窗口右侧的历史项目列表中,双击打开之前创建的单视图项目模板。 2. 本节课将为您演示,如何使用手势功能,给视图对象添加点击事件,实现视图对象的交互操作。首先在一个空白项目中,打开视图控制器的代码文件。 3. 接着开始编写代码,实现这项功能。 4. 首先初始化一个原点在(32, 80),宽度和高度都是256的矩形常量,作为视图的显示区域。 5. 然后创建一个相应尺寸的图像视图对象。 6...._ios开发中,uitap的点击区域

mips 汇编学习-程序员宅基地

文章浏览阅读124次。为什么80%的码农都做不了架构师?>>> ..._mips汇编学习感悟

人工智能与大数据:法律行业的数据分析技巧-程序员宅基地

文章浏览阅读619次,点赞18次,收藏19次。1.背景介绍人工智能(Artificial Intelligence,AI)和大数据(Big Data)技术在近年来发展迅猛,已经成为许多行业的核心技术。法律行业也不例外,人工智能和大数据技术在法律行业中的应用也越来越多。本文将讨论人工智能与大数据技术在法律行业的数据分析技巧,包括背景介绍、核心概念与联系、核心算法原理和具体操作步骤、数学模型公式详细讲解、具体代码实例和解释说明、未来发展趋势与...

2.2 离散型随机变量_离散随机变量x的取值为x1,x2,x3...xn;其整体的均值为μ;请问e(x1)=μ正确么?-程序员宅基地

文章浏览阅读835次。X(1一力1一力,k=0,1,0<力<1则称 叉 服从参数为力的0-1分布或两点分布:0-1分布的分布律也可写成力:力对对于一个随机试验,如果它的样本空间2 只包含的个样不点a1,02,我们总能在2上定义一个服从 0-1分布的随机变量0,E019X = X (00) =W= 02。定义2.3 设X是一个离散型随机变量,若X的全部可能取值为 X1,X2则Xi取龙,的概率P{X=2.1=力,i=1.2…再由Y~B(3,力),可得P{Y≥11=1-P(¥=0)=1=(1=1/③)3=19/27._离散随机变量x的取值为x1,x2,x3...xn;其整体的均值为μ;请问e(x1)=μ正确么?

Python环境搭建——集成开发环境: PyCharm_pycharm集成开发环境-程序员宅基地

文章浏览阅读1.4k次。Python环境搭建——集成开发环境:PyCharm_pycharm集成开发环境

随便推点

ssm-程序员宅基地

文章浏览阅读2k次,点赞2次,收藏2次。整合 ssm 最详细 文章 》》》https://blog.csdn.net/gebitan505/article/details/44455235

dp与px的转换-程序员宅基地

文章浏览阅读2w次,点赞3次,收藏23次。 含义:density-independent pixel,叫dp或dip,与终端上的实际物理像素点无关。 单位:dp,可以保证在不同屏幕像素密度的设备上显示相同的效果 Android开发时用dp而不是px单位设置图片大小,是Android特有的单位 场景:假如同样都是画一条长度是屏幕一半的线,如果使用px作为计量单位,那么在480x800分辨率手机上设置应为240px;在3...

linux文件分割(将大的日志文件分割成小的)_linus 把日志文件转成多个小文件-程序员宅基地

文章浏览阅读2.1k次。linux下文件分割可以通过split命令来实现,可以指定按行数分割和安大小分割两种模式。Linux下文件合并可以通过cat命令来实现,非常简单。  在Linux下用split进行文件分割:  模式一:指定分割后文件行数  对与txt文本文件,可以通过指定分割后文件的行数来进行文件分割。  命令:split -l 300 large_file.txt new_fil_linus 把日志文件转成多个小文件

许小红:全vdw光电铁电场效应晶体管集成式内存传感与计算_铁电晶体管 视觉 应用-程序员宅基地

文章浏览阅读328次,点赞7次,收藏7次。受人类视网膜的启发,一种神经形态视觉传感器可以感知光信号,存储信号,并对信息进行预处理,可以模仿人类视网膜的功能。此外,本文还模拟了突触可塑性的基本特征,包括成对脉冲促进(PPF)、短时程可塑性(STP)、长时程可塑性(LTP)、长时程增强和长时程抑制。由于冯诺依曼架构中存储与计算的物理分离,频繁的数据交互所带来的能效问题日益严峻,芯片行业迫切需要在底层计算架构层面进行创新。将内存计算作为人工智能创新的核心,避免了数据处理带来的“内存墙”和“功率墙”,显著提高了数据并行性和能效。”为题发表在著名期刊。_铁电晶体管 视觉 应用

Java集合进阶:泛型类、泛型方法、泛型接口_泛型类,泛型接口,泛型方法-程序员宅基地

文章浏览阅读308次,点赞8次,收藏5次。是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查泛型只支持引用数据类型①统一数据类型。②把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为在编译阶段类型就能确定下来。①泛型中不能写基本数据类型②指定泛型的具体类型后,传递数据时,可以传入该类类型或者其子类类型③如果不写泛型,类型默认是Object格式:修饰符 class 类名{}举例:public class ArrayList{}_泛型类,泛型接口,泛型方法

Mysql主从复制与读写分离_如何验证主从分离-程序员宅基地

文章浏览阅读346次。C_如何验证主从分离