From 55973deb0e8fcf3776e6791115c90e08c1fecef4 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Sat, 17 Jan 2015 11:58:46 +0100 Subject: [PATCH] modularize payload type matching exceptions in offer/answer --- coreapi/offeranswer.c | 125 ++++++++++++++++++++++++++++++++---------- mediastreamer2 | 2 +- 2 files changed, 97 insertions(+), 30 deletions(-) diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index d7d2e6e84..a77774457 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -31,7 +31,50 @@ static bool_t only_telephone_event(const MSList *l){ return TRUE; } -static PayloadType * find_payload_type_best_match(const MSList *l, const PayloadType *refpt){ +typedef struct _PayloadTypeMatcher{ + const char *mime_type; + PayloadType *(*match_func)(const MSList *l, const PayloadType *refpt); +}PayloadTypeMatcher; + +static PayloadType * opus_match(const MSList *l, const PayloadType *refpt){ + PayloadType *pt; + const MSList *elem; + PayloadType *candidate=NULL; + + for (elem=l;elem!=NULL;elem=elem->next){ + pt=(PayloadType*)elem->data; + + /*workaround a bug in earlier versions of linphone where opus/48000/1 is offered, which is uncompliant with opus rtp draft*/ + if (strcasecmp(pt->mime_type,"opus")==0 ){ + if (refpt->channels==1){ + pt->channels=1; /*so that we respond with same number of channels */ + candidate=pt; + }else if (refpt->channels==2){ + return pt; + } + } + } + return candidate; +} + +/* the reason for this matcher is for some stupid uncompliant phone that offer G729a mime type !*/ +static PayloadType * g729A_match(const MSList *l, const PayloadType *refpt){ + PayloadType *pt; + const MSList *elem; + PayloadType *candidate=NULL; + + for (elem=l;elem!=NULL;elem=elem->next){ + pt=(PayloadType*)elem->data; + + /*workaround a bug in earlier versions of linphone where opus/48000/1 is offered, which is uncompliant with opus rtp draft*/ + if (strcasecmp(pt->mime_type,"G729")==0 && refpt->channels==pt->channels){ + candidate=pt; + } + } + return candidate; +} + +static PayloadType * amr_match(const MSList *l, const PayloadType *refpt){ PayloadType *pt; char value[10]; const MSList *elem; @@ -40,39 +83,63 @@ static PayloadType * find_payload_type_best_match(const MSList *l, const Payload for (elem=l;elem!=NULL;elem=elem->next){ pt=(PayloadType*)elem->data; - /*workaround a bug in earlier versions of linphone where opus/48000/1 is offered, which is uncompliant with opus rtp draft*/ - if (refpt->mime_type && strcasecmp(refpt->mime_type,"opus")==0 && refpt->channels==1 - && strcasecmp(pt->mime_type,refpt->mime_type)==0){ - pt->channels=1; /*so that we respond with same number of channels */ - candidate=pt; - break; - } - - /* the compare between G729 and G729A is for some stupid uncompliant phone*/ - if ( pt->mime_type && refpt->mime_type && - (strcasecmp(pt->mime_type,refpt->mime_type)==0 || - (strcasecmp(pt->mime_type, "G729") == 0 && strcasecmp(refpt->mime_type, "G729A") == 0 )) - && pt->clock_rate==refpt->clock_rate && pt->channels==refpt->channels){ - candidate=pt; - /*good candidate, check fmtp for H264 */ - if (strcasecmp(pt->mime_type,"H264")==0){ - if (pt->recv_fmtp!=NULL && refpt->recv_fmtp!=NULL){ - int mode1=0,mode2=0; - if (fmtp_get_value(pt->recv_fmtp,"packetization-mode",value,sizeof(value))){ - mode1=atoi(value); - } - if (fmtp_get_value(refpt->recv_fmtp,"packetization-mode",value,sizeof(value))){ - mode2=atoi(value); - } - if (mode1==mode2) - break; /*exact match */ - } - }else break; + if ( pt->mime_type && refpt->mime_type + && strcasecmp(pt->mime_type, refpt->mime_type)==0 + && pt->clock_rate==refpt->clock_rate + && pt->channels==refpt->channels) { + int octedalign1=0,octedalign2=0; + if (pt->recv_fmtp!=NULL && fmtp_get_value(pt->recv_fmtp,"octet-align",value,sizeof(value))){ + octedalign1=atoi(value); + } + if (refpt->send_fmtp!=NULL && fmtp_get_value(refpt->send_fmtp,"octet-align",value,sizeof(value))){ + octedalign2=atoi(value); + } + if (octedalign1==octedalign2) { + candidate=pt; + break; /*exact match */ + } } } return candidate; } +static PayloadType * generic_match(const MSList *l, const PayloadType *refpt){ + PayloadType *pt; + const MSList *elem; + + for (elem=l;elem!=NULL;elem=elem->next){ + pt=(PayloadType*)elem->data; + + if ( pt->mime_type && refpt->mime_type + && strcasecmp(pt->mime_type, refpt->mime_type)==0 + && pt->clock_rate==refpt->clock_rate + && pt->channels==refpt->channels) + return pt; + } + return NULL; +} + +static PayloadTypeMatcher matchers[]={ + {"opus", opus_match}, + {"G729A", g729A_match}, + {"AMR", amr_match}, + {"AMR-WB", amr_match}, + {NULL, NULL} +}; + + + +static PayloadType * find_payload_type_best_match(const MSList *l, const PayloadType *refpt){ + PayloadTypeMatcher *m; + for(m=matchers;m->mime_type!=NULL;++m){ + if (refpt->mime_type && strcasecmp(m->mime_type,refpt->mime_type)==0){ + return m->match_func(l,refpt); + } + } + return generic_match(l,refpt); +} + + static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t reading_response, bool_t one_matching_codec){ const MSList *e2,*e1; MSList *res=NULL; diff --git a/mediastreamer2 b/mediastreamer2 index 0450c04a3..81e6bd551 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 0450c04a38ce2c78430208d90e41dbe23163b950 +Subproject commit 81e6bd5511c16133df340e732807d64faac1f7b2