ortp分析之一 例子分析

本文详细介绍了如何利用oRTP库中的rtpsend.c示例,实现PCMU格式音频文件或直接从声卡获取的音频流的实时发送过程。包括初始化oRTP库、配置会话、设置远程地址、负载类型、SSRC等关键步骤,并通过命令行参数灵活调整发送特性,如加入时间滑动和抖动。同时展示了如何在不同操作系统环境下打开音频文件并进行发送操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.youkuaiyun.com/ren911/article/details/5724509

一. rtpsend.c主要内容

这个例子主要是表示了PCMU格式的音频文件或者直接从声卡得到的音频流如何发送

#include <ortp/ortp.h>
#include <signal.h>
#include <stdlib.h>

#ifndef _WIN32 
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#endif

int runcond=1;

void stophandler(int signum)
{
	runcond=0;
}

static const char *help="usage: rtpsend	filename dest_ip4addr dest_port [ --with-clockslide <value> ] [ --with-jitter <milliseconds>]\n";

int main(int argc, char *argv[])
{
	RtpSession *session;
	unsigned char buffer[160];
	int i;
	FILE *infile;
	char *ssrc;
	uint32_t user_ts=0;
	int clockslide=0;
	int jitter=0;
	if (argc<4){
		printf("%s", help);
		return -1;
	}
	for(i=4;i<argc;i++){
		if (strcmp(argv[i],"--with-clockslide")==0){
			i++;
			if (i>=argc) {
				printf("%s", help);
				return -1;
			}
			clockslide=atoi(argv[i]);
			ortp_message("Using clockslide of %i milisecond every 50 packets.",clockslide);
		}else if (strcmp(argv[i],"--with-jitter")==0){
			ortp_message("Jitter will be added to outgoing stream.");
			i++;
			if (i>=argc) {
				printf("%s", help);
				return -1;
			}
			jitter=atoi(argv[i]);
		}
	}
	
	//初始化oRTP库,应该在使用oRTP API前使用 
	ortp_init();

	/*
	设置计划,scheduler可以管理多个session,在接收端可以通过select来接收多个session。
	常见的就是音频视频分两路传输,这个和后面结合起来,后面的基本都是对session的设置,
	比如对两个session设置不同的payload等  */
	ortp_scheduler_init();

	//设置log级别
	ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR);
	
	/*
	创建一个新的rtp会话,如果这个会话能够发送数据(RTP_SESSION_SENDONLY or RTP_SESSION_SENDRECV),
	输出流会被赋予一个随机的SSRC数 */
	session=rtp_session_new(RTP_SESSION_SENDONLY);	
	
	//RtpScheduler管理多个session的调度和收发的控制,本函数设置是否使用该session调度管理功能。
	rtp_session_set_scheduling_mode(session,1);

	/*
	阻塞模式只有在scheduling mode被开启的情况下才能使用,
	本函数决定了rtp_session_recv_with_ts() 和 rtp_session_send_with_ts()两个函数的行为,
	如果启用了阻塞模式,则rtp_session_recv_with_ts()会一直阻塞直到接收RTP包的时间点到达
	(这个时间点由该函数参数中所定义的时间戳来决定),当接收完RTP数据包后,该函数才会返回。
	同样,rtp_session_send_with_ts()也会一直阻塞直到需要被发送的RTP包的时间点到达,发送结束后,函数才返回。*/
	rtp_session_set_blocking_mode(session,1);

	/* 
	如果为TRUE,一个connect()系统调用将在发送到目的地的socket上使用,
	如果会话使用symmetric rtp(见rtp_session_set_symmetric_rtp(),主要用于穿越防火墙),
	一个connect()在第一个包接收后将对源地址使用。
	连接一个socket会造成拒绝所有不是从在connect()里指定的地址发送过来的包。
	它也会造成应用程序可以检测道德ICMP错误。*/ 
	rtp_session_set_connected_mode(session,TRUE);

	//设置远端地址
	rtp_session_set_remote_addr(session,argv[2],atoi(argv[3]));

	/*
	设置希望接收的包和将要发送的包的负载类型。
	如果接收包中的负载类型和希望的不同,将会发出payload_type_changed信号。可以对这个信号挂载函数处理。
	这里设置为0,实际表示payload type为PCMU,ortp里面这个设置不光设置数字就行了,
	还需要avprofile中定义的payload结构,负责会报无法识别的type */
	rtp_session_set_payload_type(session,0);
	
	ssrc=getenv("SSRC");
	if (ssrc!=NULL) {
		printf("using SSRC=%i.\n",atoi(ssrc));
		// 设置输出流的SSRC。不做此步的话将会给个随机值 
		rtp_session_set_ssrc(session,atoi(ssrc));
	}
		
	#ifndef _WIN32
	infile=fopen(argv[1],"r");
	#else
	infile=fopen(argv[1],"rb");
	#endif

	if (infile==NULL) {
		perror("Cannot open file");
		return -1;
	}

	signal(SIGINT,stophandler);
	while( ((i=fread(buffer,1,160,infile))>0) && (runcond) )
	{
		/*发送一个rtp数据报,通过rtp_session_set_remote_addr()设置目的地,以时间戳发送数据。
		发送RTP数据需要自己管理时间戳的递增,每调用一次本函数,请根据实际情况对userts进行递增,
		具体递增的规则见RTP协议中的说明。
		例如:如果发送的是采样率为90000Hz的视频数据包,每秒25帧,
		则时间戳的增量为:90000/25 = 3600时间戳的起始值为随机值,建议设置为0 。*/
		rtp_session_send_with_ts(session,buffer,i,user_ts);
		user_ts+=160;
		if (clockslide!=0 && user_ts%(160*50)==0){
			ortp_message("Clock sliding of %i miliseconds now",clockslide);
			//设置时间偏移
			rtp_session_make_time_distorsion(session,clockslide);
		}
		/*this will simulate a burst of late packets */
		//以下将会模拟一些爆发的延迟包
		if (jitter && (user_ts%(8000)==0)) {
			struct timespec pausetime, remtime;
			ortp_message("Simulating late packets now (%i milliseconds)",jitter);
			pausetime.tv_sec=jitter/1000;
			pausetime.tv_nsec=(jitter%1000)*1000000;
			while(nanosleep(&pausetime,&remtime)==-1 && errno==EINTR){
				pausetime=remtime;
			}
		}
	}

	fclose(infile);
	rtp_session_destroy(session);
	ortp_exit();
	ortp_global_stats_display();

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值