1 /*
2  * The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) implementation with additional features.
3  * Copyright (C) 2017 Belledonne Communications SARL
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19 
20 #include "ortp/ortp.h"
21 #include <bctoolbox/port.h>
22 
23 
rtp_profile_get_payload_number_from_mime(RtpProfile * profile,const char * mime)24 int rtp_profile_get_payload_number_from_mime(RtpProfile *profile, const char *mime)
25 {
26 	return rtp_profile_get_payload_number_from_mime_and_flag(profile, mime, -1);
27 }
28 
rtp_profile_get_payload_number_from_mime_and_flag(RtpProfile * profile,const char * mime,int flag)29 int rtp_profile_get_payload_number_from_mime_and_flag(RtpProfile *profile, const char *mime, int flag)
30 {
31 	PayloadType *pt;
32 	int i;
33 	for (i = 0; i < RTP_PROFILE_MAX_PAYLOADS; i++) {
34 		pt = rtp_profile_get_payload(profile, i);
35 		if (pt != NULL) {
36 			if (strcasecmp(pt->mime_type, mime) == 0) {
37 				if (flag < 0 || pt->flags & flag) {
38 					return i;
39 				}
40 			}
41 		}
42 	}
43 	return -1;
44 }
45 
rtp_profile_find_payload_number(RtpProfile * profile,const char * mime,int rate,int channels)46 int rtp_profile_find_payload_number(RtpProfile*profile,const char *mime,int rate,int channels)
47 {
48 	int i;
49 	PayloadType *pt;
50 	for (i=0;i<RTP_PROFILE_MAX_PAYLOADS;i++)
51 	{
52 		pt=rtp_profile_get_payload(profile,i);
53 		if (pt!=NULL)
54 		{
55 			if (strcasecmp(pt->mime_type,mime)==0 &&
56 			    pt->clock_rate==rate &&
57 			    (pt->channels==channels || channels<=0 || pt->channels<=0)) {
58 				/*we don't look at channels if it is undefined
59 				ie a negative or zero value*/
60 				return i;
61 			}
62 		}
63 	}
64 	return -1;
65 }
66 
rtp_profile_get_payload_number_from_rtpmap(RtpProfile * profile,const char * rtpmap)67 int rtp_profile_get_payload_number_from_rtpmap(RtpProfile *profile,const char *rtpmap)
68 {
69 	int clock_rate, channels, ret;
70 	char* subtype = ortp_strdup( rtpmap );
71 	char* rate_str = NULL;
72 	char* chan_str = NULL;
73 
74 	/* find the slash after the subtype */
75 	rate_str = strchr(subtype, '/');
76 	if (rate_str && strlen(rate_str)>1) {
77 		*rate_str = 0;
78 		rate_str++;
79 
80 		/* Look for another slash */
81 		chan_str = strchr(rate_str, '/');
82 		if (chan_str && strlen(chan_str)>1) {
83 			*chan_str = 0;
84 			chan_str++;
85 		} else {
86 			chan_str = NULL;
87 		}
88 	} else {
89 		rate_str = NULL;
90 	}
91 
92 	// Use default clock rate if none given
93 	if (rate_str) clock_rate = atoi(rate_str);
94 	else clock_rate = 8000;
95 
96 	// Use default number of channels if none given
97 	if (chan_str) channels = atoi(chan_str);
98 	else channels = -1;
99 
100 	//printf("Searching for payload %s at freq %i with %i channels\n",subtype,clock_rate,ch1annels);
101 	ret=rtp_profile_find_payload_number(profile,subtype,clock_rate,channels);
102 	ortp_free(subtype);
103 	return ret;
104 }
105 
rtp_profile_find_payload(RtpProfile * prof,const char * mime,int rate,int channels)106 PayloadType * rtp_profile_find_payload(RtpProfile *prof,const char *mime,int rate,int channels)
107 {
108 	int i;
109 	i=rtp_profile_find_payload_number(prof,mime,rate,channels);
110 	if (i>=0) return rtp_profile_get_payload(prof,i);
111 	return NULL;
112 }
113 
114 
rtp_profile_get_payload_from_mime(RtpProfile * profile,const char * mime)115 PayloadType * rtp_profile_get_payload_from_mime(RtpProfile *profile,const char *mime)
116 {
117 	int pt;
118 	pt=rtp_profile_get_payload_number_from_mime(profile,mime);
119 	if (pt==-1) return NULL;
120 	else return rtp_profile_get_payload(profile,pt);
121 }
122 
123 
rtp_profile_get_payload_from_rtpmap(RtpProfile * profile,const char * rtpmap)124 PayloadType * rtp_profile_get_payload_from_rtpmap(RtpProfile *profile, const char *rtpmap)
125 {
126 	int pt = rtp_profile_get_payload_number_from_rtpmap(profile,rtpmap);
127 	if (pt==-1) return NULL;
128 	else return rtp_profile_get_payload(profile,pt);
129 }
130 
rtp_profile_move_payload(RtpProfile * prof,int oldpos,int newpos)131 int rtp_profile_move_payload(RtpProfile *prof,int oldpos,int newpos){
132 	if (oldpos<0 || oldpos>=RTP_PROFILE_MAX_PAYLOADS) {
133 		ortp_error("Bad old pos index %i",oldpos);
134 		return -1;
135 	}
136 	if (newpos<0 || newpos>=RTP_PROFILE_MAX_PAYLOADS) {
137 		ortp_error("Bad new pos index %i",newpos);
138 		return -1;
139 	}
140 	prof->payload[newpos]=prof->payload[oldpos];
141 	prof->payload[oldpos]=NULL;
142 	return 0;
143 }
144 
rtp_profile_new(const char * name)145 RtpProfile * rtp_profile_new(const char *name)
146 {
147 	RtpProfile *prof=(RtpProfile*)ortp_new0(RtpProfile,1);
148 	rtp_profile_set_name(prof,name);
149 	return prof;
150 }
151 
152 /**
153  *	Assign payload type number index to payload type desribed in pt for the RTP profile profile.
154  * @param profile a RTP profile
155  * @param idx the payload type number
156  * @param pt the payload type description
157  *
158 **/
rtp_profile_set_payload(RtpProfile * profile,int idx,PayloadType * pt)159 void rtp_profile_set_payload(RtpProfile *profile, int idx, PayloadType *pt){
160 	if (idx<0 || idx>=RTP_PROFILE_MAX_PAYLOADS) {
161 		ortp_error("Bad index %i",idx);
162 		return;
163 	}
164 	profile->payload[idx]=pt;
165 }
166 
167 /**
168  * Initialize the profile to the empty profile (all payload type are unassigned).
169  *@param profile a RTP profile
170  *
171 **/
rtp_profile_clear_all(RtpProfile * profile)172 void rtp_profile_clear_all(RtpProfile *profile){
173 	int i;
174 	for (i=0;i<RTP_PROFILE_MAX_PAYLOADS;i++){
175 		profile->payload[i]=0;
176 	}
177 }
178 
179 
180 /**
181  * Set a name to the rtp profile. (This is not required)
182  * @param profile a rtp profile object
183  * @param name a string
184  *
185 **/
rtp_profile_set_name(RtpProfile * profile,const char * name)186 void rtp_profile_set_name(RtpProfile *profile, const char *name){
187 	if (profile->name!=NULL) ortp_free(profile->name);
188 	profile->name=ortp_strdup(name);
189 }
190 
191 /* ! payload are not cloned*/
rtp_profile_clone(RtpProfile * prof)192 RtpProfile * rtp_profile_clone(RtpProfile *prof)
193 {
194 	int i;
195 	PayloadType *pt;
196 	RtpProfile *newprof=rtp_profile_new(prof->name);
197 	for (i=0;i<RTP_PROFILE_MAX_PAYLOADS;i++){
198 		pt=rtp_profile_get_payload(prof,i);
199 		if (pt!=NULL){
200 			rtp_profile_set_payload(newprof,i,pt);
201 		}
202 	}
203 	return newprof;
204 }
205 
206 
207 /*clone a profile and its payloads */
rtp_profile_clone_full(RtpProfile * prof)208 RtpProfile * rtp_profile_clone_full(RtpProfile *prof)
209 {
210 	int i;
211 	PayloadType *pt;
212 	RtpProfile *newprof=rtp_profile_new(prof->name);
213 	for (i=0;i<RTP_PROFILE_MAX_PAYLOADS;i++){
214 		pt=rtp_profile_get_payload(prof,i);
215 		if (pt!=NULL){
216 			rtp_profile_set_payload(newprof,i,payload_type_clone(pt));
217 		}
218 	}
219 	return newprof;
220 }
221 
rtp_profile_destroy(RtpProfile * prof)222 void rtp_profile_destroy(RtpProfile *prof)
223 {
224 	int i;
225 	PayloadType *payload;
226 	if (prof->name) {
227 		ortp_free(prof->name);
228 		prof->name = NULL;
229 	}
230 	for (i=0;i<RTP_PROFILE_MAX_PAYLOADS;i++)
231 	{
232 		payload=rtp_profile_get_payload(prof,i);
233 		if (payload!=NULL && (payload->flags & PAYLOAD_TYPE_ALLOCATED))
234 			payload_type_destroy(payload);
235 	}
236 	ortp_free(prof);
237 }
238