@ -2293,21 +2293,39 @@ static void __payload_queue_free(void *qq) {
GQueue * q = qq ;
g_queue_free_full ( q , ( GDestroyNotify ) payload_type_free ) ;
}
static int __revert_codec_strip ( GHashTable * remov ed, const str * codec ,
static int __revert_codec_strip ( GHashTable * stripped, GHashTable * mask ed, const str * codec ,
struct call_media * media , struct call_media * other_media , struct supp_codec_tracker * sct )
{
GQueue * q = g_hash_table_lookup ( removed , codec ) ;
if ( ! q )
return 0 ;
ilog ( LOG_DEBUG , " Restoring codec ' " STR_FORMAT " ' from stripped codecs (%u payload types) " ,
STR_FMT ( codec ) , q - > length ) ;
g_hash_table_steal ( removed , codec ) ;
for ( GList * l = q - > head ; l ; l = l - > next ) {
struct rtp_payload_type * pt = l - > data ;
__rtp_payload_type_add ( media , other_media , pt , sct ) ;
int ret = 0 ;
GQueue * q = g_hash_table_lookup ( stripped , codec ) ;
if ( q ) {
ilog ( LOG_DEBUG , " Restoring codec ' " STR_FORMAT " ' from stripped codecs (%u payload types) " ,
STR_FMT ( codec ) , q - > length ) ;
g_hash_table_steal ( stripped , codec ) ;
for ( GList * l = q - > head ; l ; l = l - > next ) {
struct rtp_payload_type * pt = l - > data ;
__rtp_payload_type_add ( media , other_media , pt , sct ) ;
}
g_queue_free ( q ) ;
ret = 1 ;
}
g_queue_free ( q ) ;
return 1 ;
q = g_hash_table_lookup ( masked , codec ) ;
if ( q ) {
ilog ( LOG_DEBUG , " Restoring codec ' " STR_FORMAT " ' from masked codecs (%u payload types) " ,
STR_FMT ( codec ) , q - > length ) ;
g_hash_table_steal ( masked , codec ) ;
for ( GList * l = q - > head ; l ; l = l - > next ) {
struct rtp_payload_type * pt = l - > data ;
pt - > for_transcoding = 1 ;
__rtp_payload_type_add_recv ( media , pt , 1 , sct ) ;
}
g_queue_free ( q ) ;
ret = 1 ;
}
return ret ;
}
static int __codec_options_set1 ( struct call * call , struct rtp_payload_type * pt , const str * enc ,
GHashTable * codec_set )
@ -2436,6 +2454,24 @@ static void supp_codecs_fixup(struct supp_codec_tracker *sct, struct call_media
g_list_free ( supp_codecs ) ;
g_list_free ( clockrates ) ;
}
int __codec_ht_except ( int all_flag , GHashTable * yes_ht , GHashTable * no_ht , struct rtp_payload_type * pt ) {
int do_this = 0 ;
if ( all_flag )
do_this = 1 ;
if ( yes_ht ) {
if ( g_hash_table_lookup ( yes_ht , & pt - > encoding ) )
do_this = 1 ;
else if ( g_hash_table_lookup ( yes_ht , & pt - > encoding_with_params ) )
do_this = 1 ;
}
if ( no_ht ) {
if ( g_hash_table_lookup ( no_ht , & pt - > encoding ) )
do_this = 0 ;
else if ( g_hash_table_lookup ( no_ht , & pt - > encoding_with_params ) )
do_this = 0 ;
}
return do_this ;
}
void codec_rtp_payload_types ( struct call_media * media , struct call_media * other_media ,
GQueue * types , struct sdp_ng_flags * flags )
{
@ -2446,7 +2482,9 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_
struct call * call = media - > call ;
struct rtp_payload_type * pt ;
static const str str_all = STR_CONST_INIT ( " all " ) ;
GHashTable * removed = g_hash_table_new_full ( str_case_hash , str_case_equal , NULL , __payload_queue_free ) ;
static const str str_full = STR_CONST_INIT ( " full " ) ;
GHashTable * stripped = g_hash_table_new_full ( str_case_hash , str_case_equal , NULL , __payload_queue_free ) ;
GHashTable * masked = g_hash_table_new_full ( str_case_hash , str_case_equal , NULL , __payload_queue_free ) ;
int strip_all = 0 , mask_all = 0 ;
// start fresh
@ -2470,8 +2508,12 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_
if ( flags - > codec_strip & & g_hash_table_lookup ( flags - > codec_strip , & str_all ) )
strip_all = 1 ;
if ( flags - > codec_strip & & g_hash_table_lookup ( flags - > codec_strip , & str_all ) )
strip_all = 2 ;
if ( flags - > codec_mask & & g_hash_table_lookup ( flags - > codec_mask , & str_all ) )
mask_all = 1 ;
else if ( flags - > codec_mask & & g_hash_table_lookup ( flags - > codec_mask , & str_full ) )
mask_all = 2 ;
struct supp_codec_tracker sct ;
supp_codec_tracker_init ( & sct ) ;
@ -2481,34 +2523,38 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_
__rtp_payload_type_dup ( call , pt ) ; // this takes care of string allocation
// codec stripping
if ( flags - > codec_strip ) {
if ( strip_all | | g_hash_table_lookup ( flags - > codec_strip , & pt - > encoding )
| | g_hash_table_lookup ( flags - > codec_strip , & pt - > encoding_with_params ) )
{
ilog ( LOG_DEBUG , " Stripping codec ' " STR_FORMAT " ' " ,
STR_FMT ( & pt - > encoding_with_params ) ) ;
codec_touched ( pt , & sct , media ) ;
GQueue * q = g_hash_table_lookup_queue_new ( removed , & pt - > encoding ) ;
g_queue_push_tail ( q , __rtp_payload_type_copy ( pt ) ) ;
q = g_hash_table_lookup_queue_new ( removed , & pt - > encoding_with_params ) ;
g_queue_push_tail ( q , pt ) ;
continue ;
}
if ( __codec_ht_except ( strip_all , flags - > codec_strip , flags - > codec_except , pt ) ) {
ilog ( LOG_DEBUG , " Stripping codec ' " STR_FORMAT " ' " ,
STR_FMT ( & pt - > encoding_with_params ) ) ;
codec_touched ( pt , & sct , media ) ;
GQueue * q = g_hash_table_lookup_queue_new ( stripped , & pt - > encoding ) ;
g_queue_push_tail ( q , __rtp_payload_type_copy ( pt ) ) ;
q = g_hash_table_lookup_queue_new ( stripped , & pt - > encoding_with_params ) ;
g_queue_push_tail ( q , pt ) ;
continue ;
}
__codec_options_set ( call , pt , flags - > codec_set ) ;
if ( ! mask_all & & ( ! flags - > codec_mask | | ! g_hash_table_lookup ( flags - > codec_mask , & pt - > encoding ) )
& & ( ! flags - > codec_mask | | ! g_hash_table_lookup ( flags - > codec_mask , & pt - > encoding_with_params ) ) )
__rtp_payload_type_add ( media , other_media , pt , & sct ) ;
else {
// codec masking
if ( __codec_ht_except ( mask_all , flags - > codec_mask , flags - > codec_except , pt ) ) {
ilog ( LOG_DEBUG , " Masking codec ' " STR_FORMAT " ' " ,
STR_FMT ( & pt - > encoding_with_params ) ) ;
codec_touched ( pt , & sct , other_media ) ;
GQueue * q = g_hash_table_lookup_queue_new ( masked , & pt - > encoding ) ;
g_queue_push_tail ( q , __rtp_payload_type_copy ( pt ) ) ;
q = g_hash_table_lookup_queue_new ( stripped , & pt - > encoding_with_params ) ;
g_queue_push_tail ( q , __rtp_payload_type_copy ( pt ) ) ;
__rtp_payload_type_add_send ( other_media , pt ) ;
}
else
__rtp_payload_type_add ( media , other_media , pt , & sct ) ;
}
// now restore codecs that have been removed, but should be offered
for ( GList * l = flags - > codec_offer . head ; l ; l = l - > next ) {
str * codec = l - > data ;
__revert_codec_strip ( remov ed, codec , media , other_media , & sct ) ;
__revert_codec_strip ( stripped, mask ed, codec , media , other_media , & sct ) ;
}
if ( ! flags - > asymmetric_codecs ) {
@ -2534,7 +2580,8 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_
// and removed by a strip=all option,
// simply restore it from the original list and handle it the same way
// as 'offer'
if ( strip_all & & __revert_codec_strip ( removed , codec , media , other_media , & sct ) )
if ( ( strip_all = = 1 | | mask_all = = 1 )
& & __revert_codec_strip ( stripped , masked , codec , media , other_media , & sct ) )
continue ;
// also check if maybe the codec was never stripped
if ( g_hash_table_lookup ( media - > codec_names_recv , codec ) ) {
@ -2608,6 +2655,7 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_
supp_codecs_fixup ( & sct , media ) ;
g_hash_table_destroy ( removed ) ;
g_hash_table_destroy ( stripped ) ;
g_hash_table_destroy ( masked ) ;
supp_codec_tracker_destroy ( & sct ) ;
}