@ -31,25 +31,20 @@
ASTERISK_REGISTER_FILE ( )
# include <sys/resource.h> /* for rusage, getrusage, etc */
# include <sys/time.h> /* for timeval */
# include "asterisk/astobj2.h" /* for ao2_ref, ao2_cleanup, etc */
# include "asterisk/cli.h" /* for ast_cli_args, ast_cli, etc */
# include "asterisk/codec.h" /* for ast_codec, etc */
# include "asterisk/format.h" /* for ast_format_get_name, etc */
# include "asterisk/format_cache.h" /* for ast_format_cache_get, etc */
# include "asterisk/format_cap.h" /* for ast_format_cap_count, etc */
# include "asterisk/frame.h" /* for ast_frame, etc */
# include "asterisk/linkedlists.h" /* for AST_RWLIST_UNLOCK, etc */
# include "asterisk/lock.h" /* for ast_rwlock_unlock, etc */
# include "asterisk/logger.h" /* for ast_log, LOG_WARNING, etc */
# include "asterisk/module.h" /* for ast_module_unref, etc */
# include "asterisk/strings.h" /* for ast_str_append, etc */
# include "asterisk/term.h" /* for term_color, COLOR_BLACK, etc */
# include "asterisk/time.h" /* for ast_tvzero, ast_tv, etc */
# include "asterisk/translate.h" /* for ast_translator, etc */
# include "asterisk/utils.h" /* for ast_free, RAII_VAR, etc */
# include <sys/time.h>
# include <sys/resource.h>
# include <math.h>
# include "asterisk/lock.h"
# include "asterisk/channel.h"
# include "asterisk/translate.h"
# include "asterisk/module.h"
# include "asterisk/frame.h"
# include "asterisk/sched.h"
# include "asterisk/cli.h"
# include "asterisk/term.h"
# include "asterisk/format.h"
# include "asterisk/linkedlists.h"
/*! \todo
* TODO : sample frames for each supported input format .
@ -363,7 +358,6 @@ static struct ast_trans_pvt *newpvt(struct ast_translator *t, struct ast_format
pvt - > f . offset = AST_FRIENDLY_OFFSET ;
pvt - > f . src = pvt - > t - > name ;
pvt - > f . data . ptr = pvt - > outbuf . c ;
pvt - > f . seqno = 0x10000 ;
/*
* If the translator has not provided a format
@ -530,58 +524,13 @@ struct ast_trans_pvt *ast_translator_build_path(struct ast_format *dst, struct a
/*! \brief do the actual translation */
struct ast_frame * ast_translate ( struct ast_trans_pvt * path , struct ast_frame * f , int consume )
{
const unsigned int rtp_seqno_max_value = 0xffff ;
struct ast_frame * out_last , * out = NULL ;
struct ast_trans_pvt * step ;
struct ast_trans_pvt * p = path ;
struct ast_frame * out ;
struct timeval delivery ;
int has_timing_info ;
long ts ;
long len ;
int seqno , frames_missing ;
/* Determine the amount of lost packets for PLC */
/* But not when Signed Linear is involved = frame created internally */
/* But not at start with first frame = path->f.seqno is still 0x10000 */
/* But not when there is no sequence number = frame created internally */
if ( ! ast_format_cache_is_slinear ( f - > subclass . format ) & &
path - > f . seqno < = rtp_seqno_max_value & &
path - > f . seqno ! = f - > seqno ) {
if ( f - > seqno < path - > f . seqno ) { /* seqno overrun situation */
frames_missing = rtp_seqno_max_value + f - > seqno - path - > f . seqno - 1 ;
} else {
frames_missing = f - > seqno - path - > f . seqno - 1 ;
}
/* Out-of-order packet - more precise: late packet */
if ( ( rtp_seqno_max_value + 1 ) / 2 < frames_missing ) {
if ( consume ) {
ast_frfree ( f ) ;
}
/*
* Do not pass late packets to any transcoding module , because that
* confuses the state of any library ( packets inter - depend ) . With
* the next packet , this one is going to be treated as lost packet .
*/
if ( frames_missing > 96 ) { /* with 20 msec per frame, around 2 seconds late */
struct ast_str * str = ast_str_alloca ( 256 ) ;
/* Might indicate an error in the detection of Late Frames, report! */
ast_log ( LOG_NOTICE , " Late Frame; got Sequence Number %d expected %d %s \n " ,
f - > seqno , rtp_seqno_max_value & ( path - > f . seqno + 1 ) ,
ast_translate_path_to_str ( path , & str ) ) ;
}
return NULL ;
}
if ( frames_missing > 96 ) {
struct ast_str * str = ast_str_alloca ( 256 ) ;
/* not DEBUG but NOTICE because of WARNING in main/cannel.c:__ast_queue_frame */
ast_log ( LOG_NOTICE , " %d lost frame(s) %d/%d %s \n " , frames_missing ,
f - > seqno , path - > f . seqno , ast_translate_path_to_str ( path , & str ) ) ;
}
} else {
frames_missing = 0 ;
}
int seqno ;
has_timing_info = ast_test_flag ( f , AST_FRFLAG_HAS_TIMING_INFO ) ;
ts = f - > ts ;
@ -611,93 +560,18 @@ struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f,
f - > samples , ast_format_get_sample_rate ( f - > subclass . format ) ) ) ;
}
delivery = f - > delivery ;
for ( out_last = NULL ; frames_missing + 1 ; frames_missing - - ) {
struct ast_frame * frame_to_translate , * inner_head ;
struct ast_frame missed = {
. frametype = AST_FRAME_VOICE ,
. subclass . format = f - > subclass . format ,
. datalen = 0 ,
/* In RTP, the amount of samples might change anytime */
/* If that happened while frames got lost, what to do? */
. samples = f - > samples , /* FIXME */
. src = __FUNCTION__ ,
. data . uint32 = 0 ,
. delivery . tv_sec = 0 ,
. delivery . tv_usec = 0 ,
. flags = 0 ,
/* RTP sequence number is between 0x0001 and 0xffff */
. seqno = ( rtp_seqno_max_value + 1 + f - > seqno - frames_missing ) & rtp_seqno_max_value ,
} ;
if ( frames_missing ) {
frame_to_translate = & missed ;
} else {
frame_to_translate = f ;
}
/* The translation path from one format to another might contain several steps */
/* out* collects the result for missed frame(s) and input frame(s) */
/* out is the result of the conversion of all frames, translated into the destination format */
/* out_last is the last frame in that list, to add frames faster */
for ( step = path , inner_head = frame_to_translate ; inner_head & & step ; step = step - > next ) {
struct ast_frame * current , * inner_last , * inner_prev = frame_to_translate ;
/* inner* collects the result of each conversion step, the input for the next step */
/* inner_head is a list of frames created by each conversion step */
/* inner_last is the last frame in that list, to add frames faster */
for ( inner_last = NULL , current = inner_head ; current ; current = AST_LIST_NEXT ( current , frame_list ) ) {
struct ast_frame * tmp ;
framein ( step , current ) ;
tmp = step - > t - > frameout ( step ) ;
if ( ! tmp ) {
continue ;
} else if ( inner_last ) {
struct ast_frame * t ;
/* Determine the last frame of the list before appending to it */
while ( ( t = AST_LIST_NEXT ( inner_last , frame_list ) ) ) {
inner_last = t ;
}
AST_LIST_NEXT ( inner_last , frame_list ) = tmp ;
} else {
inner_prev = inner_head ;
inner_head = tmp ;
inner_last = tmp ;
}
}
/* The current step did not create any frames = no frames for the next step */
/* The steps are not lost because framein buffered those for the next input frame */
if ( ! inner_last ) {
inner_prev = inner_head ;
inner_head = NULL ;
}
if ( inner_prev ! = frame_to_translate ) {
ast_frfree ( inner_prev ) ; /* Frees just the intermediate lists */
}
}
/* This frame created no frames after translation = continue with next frame */
/* The frame is not lost because framein buffered it to be combined with the next frame */
if ( ! inner_head ) {
continue ;
} else if ( out_last ) {
struct ast_frame * t ;
/* Determine the last frame of the list before appending to it */
while ( ( t = AST_LIST_NEXT ( out_last , frame_list ) ) ) {
out_last = t ;
}
AST_LIST_NEXT ( out_last , frame_list ) = inner_head ;
} else {
out = inner_head ;
out_last = inner_head ;
for ( out = f ; out & & p ; p = p - > next ) {
struct ast_frame * current = out ;
do {
framein ( p , current ) ;
current = AST_LIST_NEXT ( current , frame_list ) ;
} while ( current ) ;
if ( out ! = f ) {
ast_frfree ( out ) ;
}
out = p - > t - > frameout ( p ) ;
}
if ( out ) {
/* we have a frame, play with times */
if ( ! ast_tvzero ( delivery ) ) {