diff --git a/channels/iax2/parser.c b/channels/iax2/parser.c index ec9d346..6eda982 100644 --- a/channels/iax2/parser.c +++ b/channels/iax2/parser.c @@ -1296,7 +1296,9 @@ void iax_frame_free(struct iax_frame *fr) ast_atomic_fetchadd_int(&frames, -1); #if !defined(LOW_MEMORY) - if (!fr->cacheable || !(iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) { + if (!fr->cacheable + || !ast_opt_cache_media_frames + || !(iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) { ast_free(fr); return; } diff --git a/configs/samples/asterisk.conf.sample b/configs/samples/asterisk.conf.sample index 30934e4..8379b6e 100644 --- a/configs/samples/asterisk.conf.sample +++ b/configs/samples/asterisk.conf.sample @@ -44,6 +44,15 @@ astsbindir => /usr/sbin ;minmemfree = 1 ; In MBs, Asterisk stops accepting new calls if ; the amount of free memory falls below this ; watermark. +;cache_media_frames = yes ; Cache media frames for performance + ; Disable this option to help track down media frame + ; mismanagement when using valgrind or MALLOC_DEBUG. + ; The cache gets in the way of determining if the + ; frame is used after being freed and who freed it. + ; NOTE: This option has no effect when Asterisk is + ; compiled with the LOW_MEMORY compile time option + ; enabled because the cache code does not exist. + ; Default yes ;cache_record_files = yes ; Cache recorded sound files to another ; directory during recording. ;record_cache_dir = /tmp ; Specify cache directory (used in conjunction diff --git a/include/asterisk/options.h b/include/asterisk/options.h index 0a20f10..878748d 100644 --- a/include/asterisk/options.h +++ b/include/asterisk/options.h @@ -66,6 +66,8 @@ enum ast_option_flags { AST_OPT_FLAG_CACHE_RECORD_FILES = (1 << 13), /*! Display timestamp in CLI verbose output */ AST_OPT_FLAG_TIMESTAMP = (1 << 14), + /*! Cache media frames for performance */ + AST_OPT_FLAG_CACHE_MEDIA_FRAMES = (1 << 15), /*! Reconnect */ AST_OPT_FLAG_RECONNECT = (1 << 16), /*! Transmit Silence during Record() and DTMF Generation */ @@ -99,7 +101,7 @@ enum ast_option_flags { }; /*! These are the options that set by default when Asterisk starts */ -#define AST_DEFAULT_OPTIONS AST_OPT_FLAG_TRANSCODE_VIA_SLIN +#define AST_DEFAULT_OPTIONS (AST_OPT_FLAG_TRANSCODE_VIA_SLIN | AST_OPT_FLAG_CACHE_MEDIA_FRAMES) #define ast_opt_exec_includes ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) #define ast_opt_no_fork ast_test_flag(&ast_options, AST_OPT_FLAG_NO_FORK) @@ -116,6 +118,7 @@ enum ast_option_flags { #define ast_opt_stdexten_macro ast_test_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO) #define ast_opt_dump_core ast_test_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE) #define ast_opt_cache_record_files ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES) +#define ast_opt_cache_media_frames ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_MEDIA_FRAMES) #define ast_opt_timestamp ast_test_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP) #define ast_opt_reconnect ast_test_flag(&ast_options, AST_OPT_FLAG_RECONNECT) #define ast_opt_transmit_silence ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) diff --git a/main/asterisk.c b/main/asterisk.c index d555949..98dbd9f 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -607,6 +607,9 @@ static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_c ast_cli(a->fd, " Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) ? "Enabled" : "Disabled"); ast_cli(a->fd, " Generic PLC: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled"); ast_cli(a->fd, " Min DTMF duration:: %u\n", option_dtmfminduration); +#if !defined(LOW_MEMORY) + ast_cli(a->fd, " Cache media frames: %s\n", ast_opt_cache_media_frames ? "Enabled" : "Disabled"); +#endif ast_cli(a->fd, " RTP use dynamic payloads: %u\n", ast_option_rtpusedynamic); if (ast_option_rtpptdynamic == AST_RTP_PT_LAST_REASSIGN) { @@ -3724,6 +3727,11 @@ static void ast_readconfig(void) /* Cache recorded sound files to another directory during recording */ } else if (!strcasecmp(v->name, "cache_record_files")) { ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES); +#if !defined(LOW_MEMORY) + /* Cache media frames for performance */ + } else if (!strcasecmp(v->name, "cache_media_frames")) { + ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_MEDIA_FRAMES); +#endif /* Specify cache directory */ } else if (!strcasecmp(v->name, "record_cache_dir")) { ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN); diff --git a/main/frame.c b/main/frame.c index c24cc8f..690d48e 100644 --- a/main/frame.c +++ b/main/frame.c @@ -120,14 +120,18 @@ static void __frame_free(struct ast_frame *fr, int cache) return; #if !defined(LOW_MEMORY) - if (cache && fr->mallocd == AST_MALLOCD_HDR) { + if (fr->mallocd == AST_MALLOCD_HDR + && cache + && ast_opt_cache_media_frames) { /* Cool, only the header is malloc'd, let's just cache those for now * to keep things simple... */ struct ast_frame_cache *frames; - if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) && - (frames->size < FRAME_CACHE_MAX_SIZE)) { - if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) || - (fr->frametype == AST_FRAME_IMAGE)) { + + frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)); + if (frames && frames->size < FRAME_CACHE_MAX_SIZE) { + if (fr->frametype == AST_FRAME_VOICE + || fr->frametype == AST_FRAME_VIDEO + || fr->frametype == AST_FRAME_IMAGE) { ao2_cleanup(fr->subclass.format); } @@ -147,8 +151,9 @@ static void __frame_free(struct ast_frame *fr, int cache) ast_free((void *) fr->src); } if (fr->mallocd & AST_MALLOCD_HDR) { - if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) || - (fr->frametype == AST_FRAME_IMAGE)) { + if (fr->frametype == AST_FRAME_VOICE + || fr->frametype == AST_FRAME_VIDEO + || fr->frametype == AST_FRAME_IMAGE) { ao2_cleanup(fr->subclass.format); }