]> sjero.net Git - linphone/blob - coreapi/offeranswer.c
work in progress, new layout
[linphone] / coreapi / offeranswer.c
1 /*
2 linphone
3 Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (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 "sal.h"
21 #include "offeranswer.h"
22
23
24 static PayloadType * find_payload_type_best_match(const MSList *l, const PayloadType *refpt){
25         PayloadType *pt;
26         char value[10];
27         const MSList *elem;
28         PayloadType *candidate=NULL;
29
30         for (elem=l;elem!=NULL;elem=elem->next){
31                 pt=(PayloadType*)elem->data;
32                 if (strcasecmp(pt->mime_type,refpt->mime_type)==0 && pt->clock_rate==refpt->clock_rate){
33                         candidate=pt;
34                         /*good candidate, check fmtp for H264 */
35                         if (strcasecmp(pt->mime_type,"H264")==0){
36                                 if (pt->recv_fmtp!=NULL && refpt->recv_fmtp!=NULL){
37                                         int mode1=0,mode2=0;
38                                         if (fmtp_get_value(pt->recv_fmtp,"packetization-mode",value,sizeof(value))){
39                                                 mode1=atoi(value);
40                                         }
41                                         if (fmtp_get_value(refpt->recv_fmtp,"packetization-mode",value,sizeof(value))){
42                                                 mode2=atoi(value);
43                                         }
44                                         if (mode1==mode2)
45                                             break; /*exact match */
46                                 }
47                         }else break;
48                 }
49         }
50         return candidate;
51 }
52
53 static MSList *match_payloads(const MSList *local, const MSList *remote){
54         const MSList *e2;
55         MSList *res=NULL;
56         PayloadType *matched;
57         for(e2=remote;e2!=NULL;e2=e2->next){
58                 PayloadType *p2=(PayloadType*)e2->data;
59                 matched=find_payload_type_best_match(local,p2);
60                 if (matched){
61                         matched=payload_type_clone(matched);
62                         if (p2->recv_fmtp)
63                                 payload_type_set_send_fmtp(matched,p2->recv_fmtp);
64                         res=ms_list_append(res,matched);
65                         payload_type_set_number(matched,payload_type_get_number(p2));
66                 }else{
67                         ms_message("No match for %s/%i",p2->mime_type,p2->clock_rate);
68                 }
69         }
70         return res;
71 }
72
73 static bool_t only_telephone_event(const MSList *l){
74         for(;l!=NULL;l=l->next){
75                 PayloadType *p=(PayloadType*)l->data;
76                 if (strcasecmp(p->mime_type,"telephone-event")!=0){
77                         return FALSE;
78                 }
79         }
80         return TRUE;
81 }
82
83 static void initiate_outgoing(const SalStreamDescription *local_offer,
84                                         const SalStreamDescription *remote_answer,
85                                         SalStreamDescription *result){
86         result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads);
87         if (result->payloads && !only_telephone_event(result->payloads)){
88                 result->port=remote_answer->port;
89                 result->bandwidth=remote_answer->bandwidth;
90                 result->ptime=remote_answer->ptime;
91         }else{
92                 result->port=0;
93         }
94 }
95
96
97 static void initiate_incoming(const SalStreamDescription *local_cap,
98                                         const SalStreamDescription *remote_offer,
99                                         SalStreamDescription *result){
100         result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads);
101         if (result->payloads && !only_telephone_event(result->payloads)){
102                 result->port=remote_offer->port;
103                 result->bandwidth=remote_offer->bandwidth;
104                 result->ptime=remote_offer->ptime;
105         }else{
106                 result->port=0;
107         }
108 }
109
110 /**
111  * Returns a media description to run the streams with, based on a local offer
112  * and the returned response (remote).
113 **/
114 int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
115                                                                         const SalMediaDescription *remote_answer,
116                                                         SalMediaDescription *result){
117     int i;
118     for(i=0;i<local_offer->nstreams;++i){
119         initiate_outgoing(&local_offer->streams[i],&remote_answer->streams[i],&result->streams[i]);
120     }
121         result->nstreams=local_offer->nstreams;
122         strcpy(result->addr,remote_answer->addr);
123         return 0;
124 }
125
126 /**
127  * Returns a media description to run the streams with, based on the local capabilities and
128  * and the received offer.
129  * The returned media description is an answer and should be sent to the offerer.
130 **/
131 int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities,
132                                                 const SalMediaDescription *remote_offer,
133                                         SalMediaDescription *result){
134     int i;
135     for(i=0;i<local_capabilities->nstreams;++i){
136         initiate_incoming(&local_capabilities->streams[i],&remote_offer->streams[i],&result->streams[i]);
137     }
138         result->nstreams=local_capabilities->nstreams;
139         strcpy(result->addr,remote_offer->addr);
140         return 0;
141 }
142