@ -298,6 +298,10 @@ static void destroy(struct ast_trans_pvt *pvt)
t - > destroy ( pvt ) ;
}
ao2_cleanup ( pvt - > f . subclass . format ) ;
if ( pvt - > explicit_dst ) {
ao2_ref ( pvt - > explicit_dst , - 1 ) ;
pvt - > explicit_dst = NULL ;
}
ast_free ( pvt ) ;
ast_module_unref ( t - > module ) ;
}
@ -306,7 +310,7 @@ static void destroy(struct ast_trans_pvt *pvt)
* \ brief Allocate the descriptor , required outbuf space ,
* and possibly desc .
*/
static struct ast_trans_pvt * newpvt ( struct ast_translator * t )
static struct ast_trans_pvt * newpvt ( struct ast_translator * t , struct ast_format * explicit_dst )
{
struct ast_trans_pvt * pvt ;
int len ;
@ -332,6 +336,12 @@ static struct ast_trans_pvt *newpvt(struct ast_translator *t)
if ( t - > buf_size ) { /* finally buffer and header */
pvt - > outbuf . c = ofs + AST_FRIENDLY_OFFSET ;
}
/*
* If the format has an attribute module , explicit_dst includes the ( joined )
* result of the SDP negotiation . For example with the Opus Codec , the format
* knows whether both parties want to do forward - error correction ( FEC ) .
*/
pvt - > explicit_dst = ao2_bump ( explicit_dst ) ;
ast_module_ref ( t - > module ) ;
@ -349,9 +359,16 @@ static struct ast_trans_pvt *newpvt(struct ast_translator *t)
pvt - > f . src = pvt - > t - > name ;
pvt - > f . data . ptr = pvt - > outbuf . c ;
/* if the translator has not provided a format find one in the cache or create one */
/*
* If the translator has not provided a format
* A ) use the joined one ,
* B ) use the cached one , or
* C ) create one .
*/
if ( ! pvt - > f . subclass . format ) {
if ( ! ast_strlen_zero ( pvt - > t - > format ) ) {
pvt - > f . subclass . format = ao2_bump ( pvt - > explicit_dst ) ;
if ( ! pvt - > f . subclass . format & & ! ast_strlen_zero ( pvt - > t - > format ) ) {
pvt - > f . subclass . format = ast_format_cache_get ( pvt - > t - > format ) ;
}
@ -477,6 +494,7 @@ struct ast_trans_pvt *ast_translator_build_path(struct ast_format *dst, struct a
while ( src_index ! = dst_index ) {
struct ast_trans_pvt * cur ;
struct ast_format * explicit_dst = NULL ;
struct ast_translator * t = matrix_get ( src_index , dst_index ) - > step ;
if ( ! t ) {
ast_log ( LOG_WARNING , " No translator path from %s to %s \n " ,
@ -484,7 +502,10 @@ struct ast_trans_pvt *ast_translator_build_path(struct ast_format *dst, struct a
AST_RWLIST_UNLOCK ( & translators ) ;
return NULL ;
}
if ( ! ( cur = newpvt ( t ) ) ) {
if ( ( t - > dst_codec . sample_rate = = ast_format_get_sample_rate ( dst ) ) & & ( t - > dst_codec . type = = ast_format_get_type ( dst ) ) & & ( ! strcmp ( t - > dst_codec . name , ast_format_get_name ( dst ) ) ) ) {
explicit_dst = dst ;
}
if ( ! ( cur = newpvt ( t , explicit_dst ) ) ) {
ast_log ( LOG_WARNING , " Failed to build translator step from %s to %s \n " ,
ast_format_get_name ( src ) , ast_format_get_name ( dst ) ) ;
if ( head ) {
@ -638,7 +659,7 @@ static void generate_computational_cost(struct ast_translator *t, int seconds)
return ;
}
pvt = newpvt ( t );
pvt = newpvt ( t , NULL );
if ( ! pvt ) {
ast_log ( LOG_WARNING , " Translator '%s' appears to be broken and will probably fail. \n " , t - > name ) ;
t - > comp_cost = 999999 ;