⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtp.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
									delta,									ch->Jitter >> 4,									lost,									ch->total_pck,									ch->total_bytes				));	}#endif	//we work with no CSRC so payload offset is always 12	*PayloadStart = 12;	//store the time	ch->CurrentTime = rtp_hdr->TimeStamp;	return e;}GF_EXPORTDouble gf_rtp_get_current_time(GF_RTPChannel *ch){	Double ret;	if (!ch) return 0.0;	ret = (Double) ch->CurrentTime;	ret -= (Double) ch->rtp_time;	ret /= ch->TimeScale;	return ret;}GF_EXPORTGF_Err gf_rtp_send_packet(GF_RTPChannel *ch, GF_RTPHeader *rtp_hdr, char *extra_header, u32 extra_header_size, char *pck, u32 pck_size){	GF_Err e;	u32 Start, i;	GF_BitStream *bs;	if (!ch || !rtp_hdr 		|| !ch->send_buffer 		|| !pck 		|| (rtp_hdr->CSRCCount && !rtp_hdr->CSRC) 		|| (rtp_hdr->CSRCCount > 15)) return GF_BAD_PARAM;		if (12 + extra_header_size + pck_size + 4*rtp_hdr->CSRCCount > ch->send_buffer_size) return GF_IO_ERR; 	//we don't support multiple CSRC now. Only one source (the server) is allowed	if (rtp_hdr->CSRCCount) return GF_NOT_SUPPORTED;	bs = gf_bs_new(ch->send_buffer, ch->send_buffer_size, GF_BITSTREAM_WRITE);		//write header	gf_bs_write_int(bs, rtp_hdr->Version, 2);	gf_bs_write_int(bs, rtp_hdr->Padding, 1);	gf_bs_write_int(bs, rtp_hdr->Extension, 1);	gf_bs_write_int(bs, rtp_hdr->CSRCCount, 4);	gf_bs_write_int(bs, rtp_hdr->Marker, 1);	gf_bs_write_int(bs, rtp_hdr->PayloadType, 7);	gf_bs_write_u16(bs, rtp_hdr->SequenceNumber);	gf_bs_write_u32(bs, rtp_hdr->TimeStamp);	gf_bs_write_u32(bs, rtp_hdr->SSRC);	for (i=0; i<rtp_hdr->CSRCCount; i++) {		gf_bs_write_u32(bs, rtp_hdr->CSRC[i]);	}	//nb: RTP header is always aligned	Start = (u32) gf_bs_get_position(bs);	gf_bs_del(bs);	//extra header	if (extra_header_size) {		memcpy(ch->send_buffer + Start, extra_header, extra_header_size);		Start += extra_header_size;	}	//payload	memcpy(ch->send_buffer + Start, pck, pck_size);	e = gf_sk_send(ch->rtp, ch->send_buffer, Start + pck_size);	if (e) return e;	//Update RTCP for sender reports	ch->pck_sent_since_last_sr += 1;	if (ch->first_SR) {		//get a new report time		gf_rtp_get_next_report_time(ch);		ch->num_payload_bytes = 0;		ch->num_pck_sent = 0;		ch->first_SR = 0;	}	ch->num_payload_bytes += pck_size + extra_header_size;	ch->num_pck_sent += 1;	//store timing	ch->last_pck_ts = rtp_hdr->TimeStamp;	gf_net_get_ntp(&ch->last_pck_ntp_sec, &ch->last_pck_ntp_frac);	return GF_OK;}GF_EXPORTu32 gf_rtp_is_unicast(GF_RTPChannel *ch){	if (!ch) return 0;	return ch->net_info.IsUnicast;}GF_EXPORTu32 gf_rtp_is_interleaved(GF_RTPChannel *ch){	if (!ch || !ch->net_info.Profile) return 0;	return ch->net_info.IsInterleaved;}GF_EXPORTu32 gf_rtp_get_clockrate(GF_RTPChannel *ch){	if (!ch || !ch->TimeScale) return 0;	return ch->TimeScale;}GF_EXPORTu32 gf_rtp_is_active(GF_RTPChannel *ch){	if (!ch) return 0;	if (!ch->rtp_first_SN && !ch->rtp_time) return 0;	return 1;}GF_EXPORTu8 gf_rtp_get_low_interleave_id(GF_RTPChannel *ch){	if (!ch || !ch->net_info.IsInterleaved) return 0;	return ch->net_info.rtpID;}GF_EXPORTu8 gf_rtp_get_hight_interleave_id(GF_RTPChannel *ch){	if (!ch || !ch->net_info.IsInterleaved) return 0;	return ch->net_info.rtcpID;}#define RTP_DEFAULT_FIRSTPORT		7040static u16 NextAvailablePort = 0;GF_EXPORTGF_Err gf_rtp_set_ports(GF_RTPChannel *ch, u16 first_port){	u32 retry;	u16 p;	GF_Socket *sock;	if (!ch) return GF_BAD_PARAM;	if (!NextAvailablePort) {		NextAvailablePort = first_port ? first_port : RTP_DEFAULT_FIRSTPORT;	}	p = NextAvailablePort;	if (ch->net_info.client_port_first) return GF_OK;	sock = gf_sk_new(GF_SOCK_TYPE_UDP);	if (!sock) return GF_IO_ERR;	/*should be way enough (more than 100 rtp streams open on the machine)*/	retry = 100;	while (1) {		/*try to bind without reuse. If fails this means the port is used on the machine, don't reuse it*/		GF_Err e = gf_sk_bind(sock, p, NULL, 0, 0);		if (e==GF_OK) break;		if (e!=GF_IP_CONNECTION_FAILURE) {			gf_sk_del(sock);			return GF_IP_NETWORK_FAILURE;		}		p+=2;	}	gf_sk_del(sock);	ch->net_info.client_port_first = p;	ch->net_info.client_port_last = p + 1;	NextAvailablePort = p + 2;	return GF_OK;}GF_EXPORTGF_Err gf_rtp_setup_payload(GF_RTPChannel *ch, GF_RTPMap *map){	if (!ch || !map) return GF_BAD_PARAM;	ch->PayloadType = map->PayloadType;	ch->TimeScale = map->ClockRate;	return GF_OK;}GF_EXPORTGF_RTSPTransport *gf_rtp_get_transport(GF_RTPChannel *ch){	if (!ch) return NULL;	return &ch->net_info;}GF_EXPORTu32 gf_rtp_get_local_ssrc(GF_RTPChannel *ch){	if (!ch) return 0;	return ch->SSRC;}#if 0	"#RTP log format:\n"	"#RTP SenderSSRC RTP_TimeStamp RTP_SeqNum NTP@Recv Deviance Jitter NbLost NbTotPck NbTotBytes\n"	"#RTCP Sender reports log format:\n"	"#RTCP-SR SenderSSRC RTP_TimeStamp@NTP NbTotPck NbTotBytes NTP\n"	"#RTCP Receiver reports log format:\n"	"#RTCP-RR StreamSSRC Jitter ExtendedSeqNum ExpectDiff LossDiff NTP\n"#endifGF_EXPORTFloat gf_rtp_get_loss(GF_RTPChannel *ch){	if (!ch->tot_num_pck_expected) return 0.0f;	return 100.0f - (100.0f * ch->tot_num_pck_rcv) / ch->tot_num_pck_expected;}GF_EXPORTu32 gf_rtp_get_tcp_bytes_sent(GF_RTPChannel *ch){	return ch->rtcp_bytes_sent;}GF_EXPORTvoid gf_rtp_get_ports(GF_RTPChannel *ch, u16 *rtp_port, u16 *rtcp_port){	*rtp_port = ch->net_info.client_port_first;	*rtcp_port = ch->net_info.client_port_last;}/*	RTP packet reorderer*/#define SN_CHECK_OFFSET		0x0AGF_RTPReorder *gf_rtp_reorderer_new(u32 MaxCount, u32 MaxDelay){	GF_RTPReorder *tmp;		if (MaxCount <= 1 || !MaxDelay) return NULL;	GF_SAFEALLOC(tmp , GF_RTPReorder);	tmp->MaxCount = MaxCount;	tmp->MaxDelay = MaxDelay;	return tmp;}static void DelItem(GF_POItem *it){	if (it) {		if (it->next) DelItem(it->next);		free(it->pck);		free(it);	}}void gf_rtp_reorderer_del(GF_RTPReorder *po){	if (po->in) DelItem(po->in);	free(po);}void gf_rtp_reorderer_reset(GF_RTPReorder *po){	if (!po) return;	if (po->in) DelItem(po->in);	po->head_seqnum = 0;	po->Count = 0;	po->IsInit = 0;	po->in = NULL;}GF_Err gf_rtp_reorderer_add(GF_RTPReorder *po, void *pck, u32 pck_size, u32 pck_seqnum){	GF_POItem *it, *cur;	u32 bounds;	if (!po) return GF_BAD_PARAM;	it = (GF_POItem *) malloc(sizeof(GF_POItem));	it->pck_seq_num = pck_seqnum;	it->next = NULL;	it->size = pck_size;	it->pck = malloc(pck_size);	memcpy(it->pck, pck, pck_size);	/*reset timeout*/	po->LastTime = 0;	//no input, this packet will be the input	if (!po->in) {		//the seq num was not initialized		if (!po->head_seqnum) {			po->head_seqnum = pck_seqnum;		} else if (!po->IsInit) {			//this is not in our current range for init			if (ABSDIFF(po->head_seqnum, pck_seqnum) > SN_CHECK_OFFSET) goto discard;			po->IsInit = 1;		}		po->in = it;		po->Count += 1;		return GF_OK;	}	//this is 16 bitr seq num, as we work with RTP only for now	bounds = 0;	if ( (po->head_seqnum >= 0xf000 ) || (po->head_seqnum <= 0x1000) ) bounds = 0x2000;	//first check the head of the list	//same seq num, we drop	if (po->in->pck_seq_num == pck_seqnum) goto discard;	if ( ( (u16) (pck_seqnum + bounds) <= (u16) (po->in->pck_seq_num + bounds) )		&& ( (u16) (pck_seqnum + bounds) >= (u16) (po->head_seqnum + bounds)) ) {		it->next = po->in;		po->in = it;		po->Count += 1;		GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[rtp] Packet Reorderer: inserting packet %d at head\n", pck_seqnum));		return GF_OK;	}	//no, insert at the right place	cur = po->in;	while (1) {		//same seq num, we drop		if (cur->pck_seq_num == pck_seqnum) goto discard;		//end of list		if (!cur->next) {			cur->next = it;			po->Count += 1;#ifndef GPAC_DISABLE_LOG			if (cur->pck_seq_num +1 != it->pck_seq_num) 				GF_LOG(GF_LOG_WARNING, GF_LOG_RTP, ("[rtp] Packet Reorderer: got %d expected %d\n", cur->pck_seq_num+1, it->pck_seq_num));			GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[rtp] Packet Reorderer: Appending packet %d\n", pck_seqnum));#endif			return GF_OK;		}		//are we in the bounds ??		if ( ( (u16) (cur->pck_seq_num + bounds) < (u16) (pck_seqnum + bounds) )			&& ( (u16) (pck_seqnum + bounds) < (u16) (cur->next->pck_seq_num + bounds)) ) {			//insert			it->next = cur->next;			cur->next = it;			po->Count += 1;			GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[rtp] Packet Reorderer: Inserting packet %d", pck_seqnum));			//done			return GF_OK;		}		cur = cur->next;	}	discard:	free(it->pck);	free(it);	GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[rtp] Packet Reorderer: Dropping packet %d", pck_seqnum));	return GF_OK;}//retrieve the first available packet. Note that the behavior will be undefined if the first//ever recieved packet if its SeqNum was unknown//the BUFFER is yours, you must delete itvoid *gf_rtp_reorderer_get(GF_RTPReorder *po, u32 *pck_size){	GF_POItem *t;	u32 bounds;	void *ret;	if (!po || !pck_size) return NULL;	*pck_size = 0;	//empty queue	if (!po->in) return NULL;	//check we have recieved the first packet	if ( po->head_seqnum && po->MaxCount		&& (po->MaxCount > po->Count) 		&& (po->in->pck_seq_num != po->head_seqnum)) 		return NULL;	//no entry	if (!po->in->next) goto check_timeout;	bounds = 0;	if ( (po->head_seqnum >= 0xf000 ) || (po->head_seqnum <= 0x1000) ) bounds = 0x2000;	//release the output if SN in order or maxCount reached	if (( (u16) (po->in->pck_seq_num + bounds + 1) == (u16) (po->in->next->pck_seq_num + bounds)) 		|| (po->MaxCount && po->Count == po->MaxCount) ) {#ifndef GPAC_DISABLE_LOG		if (po->in->pck_seq_num + 1 != po->in->next->pck_seq_num) 			GF_LOG(GF_LOG_WARNING, GF_LOG_RTP, ("[rtp] Packet Reorderer: Fetched %d expected %d\n", po->in->pck_seq_num, po->in->next->pck_seq_num));#endif		goto send_it;	}	//update timing	else {check_timeout:		if (!po->LastTime) {			po->LastTime = gf_sys_clock();			GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[rtp] Packet Reorderer: starting timeout at %d\n", po->LastTime));			return NULL;		}		//if exceeding the delay send the head		if (gf_sys_clock() - po->LastTime >= po->MaxDelay) {			GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[rtp] Packet Reorderer: Forcing output after %d ms wait (max allowed %d)\n", gf_sys_clock() - po->LastTime, po->MaxDelay));			goto send_it;		}	}	return NULL;send_it:	GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[rtp] Packet Reorderer: Fetching %d\n", po->in->pck_seq_num));	*pck_size = po->in->size;	t = po->in;	po->in = po->in->next;	//no other output. reset the head seqnum	po->head_seqnum = po->in ? po->in->pck_seq_num : 0;	po->Count -= 1;	//release the item	ret = t->pck;	free(t);	return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -