From c611dcc32df7c36ce58f2f0a3ee3c32f5839582d Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Thu, 12 Jun 2014 12:20:10 -0400 Subject: [PATCH] Bug 1024288: Allow aec debug data to be dumped on the fly, with max size r=pkerr --- build/gyp.mozbuild | 2 +- .../modules/audio_processing/aec/aec_core.c | 90 +++++++++++++++---- .../audio_processing/aec/aec_core_internal.h | 1 + .../audio_processing/aec/echo_cancellation.c | 76 ++++++++++++---- .../webrtc/system_wrappers/interface/trace.h | 14 +++ .../system_wrappers/source/trace_impl.cc | 8 ++ 6 files changed, 155 insertions(+), 36 deletions(-) diff --git a/build/gyp.mozbuild b/build/gyp.mozbuild index e9a6064564be..001cce6cd084 100644 --- a/build/gyp.mozbuild +++ b/build/gyp.mozbuild @@ -43,7 +43,7 @@ gyp_vars = { # (for vp8) chromium sets to 0 also 'use_temporal_layers': 0, # Creates AEC internal sample dump files in current directory - # 'aec_debug_dump': 1, + 'aec_debug_dump': 1, # codec enable/disables: 'include_g711': 1, diff --git a/media/webrtc/trunk/webrtc/modules/audio_processing/aec/aec_core.c b/media/webrtc/trunk/webrtc/modules/audio_processing/aec/aec_core.c index 7dda551f3d85..99a140cfe95b 100644 --- a/media/webrtc/trunk/webrtc/modules/audio_processing/aec/aec_core.c +++ b/media/webrtc/trunk/webrtc/modules/audio_processing/aec/aec_core.c @@ -28,6 +28,9 @@ #include "webrtc/system_wrappers/interface/cpu_features_wrapper.h" #include "webrtc/typedefs.h" +extern int AECDebug(); +void OpenCoreDebugFiles(AecCore* aec, int *instance_count); + // Buffer size (samples) static const size_t kBufSizePartitions = 250; // 1 second of audio in 16 kHz. @@ -211,17 +214,9 @@ int WebRtcAec_CreateAec(AecCore** aecInst) { aec = NULL; return -1; } - { - char filename[64]; - sprintf(filename, "aec_far%d.pcm", webrtc_aec_instance_count); - aec->farFile = fopen(filename, "wb"); - sprintf(filename, "aec_near%d.pcm", webrtc_aec_instance_count); - aec->nearFile = fopen(filename, "wb"); - sprintf(filename, "aec_out%d.pcm", webrtc_aec_instance_count); - aec->outFile = fopen(filename, "wb"); - sprintf(filename, "aec_out_linear%d.pcm", webrtc_aec_instance_count); - aec->outLinearFile = fopen(filename, "wb"); - } + aec->outLinearFile = aec->outFile = aec->nearFile = aec->farFile = NULL; + aec->debugWritten = 0; + OpenCoreDebugFiles(aec, &webrtc_aec_instance_count); #endif aec->delay_estimator_farend = WebRtc_CreateDelayEstimatorFarend(PART_LEN1, kHistorySizeBlocks); @@ -256,10 +251,13 @@ int WebRtcAec_FreeAec(AecCore* aec) { WebRtc_FreeBuffer(aec->far_buf_windowed); #ifdef WEBRTC_AEC_DEBUG_DUMP WebRtc_FreeBuffer(aec->far_time_buf); - fclose(aec->farFile); - fclose(aec->nearFile); - fclose(aec->outFile); - fclose(aec->outLinearFile); + if (aec->farFile) { + // we don't let one be open and not the others + fclose(aec->farFile); + fclose(aec->nearFile); + fclose(aec->outFile); + fclose(aec->outLinearFile); + } #endif WebRtc_FreeDelayEstimator(aec->delay_estimator); WebRtc_FreeDelayEstimatorFarend(aec->delay_estimator_farend); @@ -848,8 +846,15 @@ static void ProcessBlock(AecCore* aec) { int16_t farend[PART_LEN]; int16_t* farend_ptr = NULL; WebRtc_ReadBuffer(aec->far_time_buf, (void**)&farend_ptr, farend, 1); - (void)fwrite(farend_ptr, sizeof(int16_t), PART_LEN, aec->farFile); - (void)fwrite(nearend_ptr, sizeof(int16_t), PART_LEN, aec->nearFile); + OpenCoreDebugFiles(aec, &webrtc_aec_instance_count); + if (aec->farFile) { + (void)fwrite(farend_ptr, sizeof(int16_t), PART_LEN, aec->farFile); + (void)fwrite(nearend_ptr, sizeof(int16_t), PART_LEN, aec->nearFile); + aec->debugWritten += sizeof(int16_t) * PART_LEN; + if (aec->debugWritten >= AECDebugMaxSize()) { + AECDebugEnable(0); + } + } } #endif @@ -1006,8 +1011,11 @@ static void ProcessBlock(AecCore* aec) { WEBRTC_SPL_WORD16_MAX, e[i], WEBRTC_SPL_WORD16_MIN); } - (void)fwrite(eInt16, sizeof(int16_t), PART_LEN, aec->outLinearFile); - (void)fwrite(output, sizeof(int16_t), PART_LEN, aec->outFile); + OpenCoreDebugFiles(aec, &webrtc_aec_instance_count); + if (aec->outLinearFile) { + (void)fwrite(eInt16, sizeof(int16_t), PART_LEN, aec->outLinearFile); + (void)fwrite(output, sizeof(int16_t), PART_LEN, aec->outFile); + } } #endif } @@ -1711,3 +1719,47 @@ static void TimeToFrequency(float time_data[PART_LEN2], } } +#ifdef WEBRTC_AEC_DEBUG_DUMP +void +OpenCoreDebugFiles(AecCore* aec, + int *instance_count) +{ + int error = 0; + // XXX If this impacts performance (opening files here), move file open + // to Trace::set_aec_debug(), and just grab them here + if (AECDebug() && !aec->farFile) { + char filename[128]; + if (!aec->farFile) { + sprintf(filename, "aec_far%d.pcm", webrtc_aec_instance_count); + aec->farFile = fopen(filename, "wb"); + sprintf(filename, "aec_near%d.pcm", webrtc_aec_instance_count); + aec->nearFile = fopen(filename, "wb"); + sprintf(filename, "aec_out%d.pcm", webrtc_aec_instance_count); + aec->outFile = fopen(filename, "wb"); + sprintf(filename, "aec_out_linear%d.pcm", webrtc_aec_instance_count); + aec->outLinearFile = fopen(filename, "wb"); + aec->debugWritten = 0; + if (!aec->outLinearFile || !aec->outFile || !aec->nearFile || !aec->farFile) { + error = 1; + } + } + } + if (error || + (!AECDebug() && aec->farFile)) { + if (aec->farFile) { + fclose(aec->farFile); + } + if (aec->nearFile) { + fclose(aec->nearFile); + } + if (aec->outFile) { + fclose(aec->outFile); + } + if (aec->outLinearFile) { + fclose(aec->outLinearFile); + } + aec->outLinearFile = aec->outFile = aec->nearFile = aec->farFile = NULL; + aec->debugWritten = 0; + } +} +#endif diff --git a/media/webrtc/trunk/webrtc/modules/audio_processing/aec/aec_core_internal.h b/media/webrtc/trunk/webrtc/modules/audio_processing/aec/aec_core_internal.h index 193369382ca0..8655d47cd80f 100644 --- a/media/webrtc/trunk/webrtc/modules/audio_processing/aec/aec_core_internal.h +++ b/media/webrtc/trunk/webrtc/modules/audio_processing/aec/aec_core_internal.h @@ -133,6 +133,7 @@ struct AecCore { FILE* nearFile; FILE* outFile; FILE* outLinearFile; + uint32_t debugWritten; #endif }; diff --git a/media/webrtc/trunk/webrtc/modules/audio_processing/aec/echo_cancellation.c b/media/webrtc/trunk/webrtc/modules/audio_processing/aec/echo_cancellation.c index bbdd5f628b23..2bc06c47ac70 100644 --- a/media/webrtc/trunk/webrtc/modules/audio_processing/aec/echo_cancellation.c +++ b/media/webrtc/trunk/webrtc/modules/audio_processing/aec/echo_cancellation.c @@ -27,6 +27,8 @@ #include "webrtc/modules/audio_processing/utility/ring_buffer.h" #include "webrtc/typedefs.h" +extern int AECDebug(); + // Measured delays [ms] // Device Chrome GTP // MacBook Air 10 @@ -165,16 +167,9 @@ int32_t WebRtcAec_Create(void** aecInst) { aecpc = NULL; return -1; } - { - char filename[64]; - sprintf(filename, "aec_buf%d.dat", webrtc_aec_instance_count); - aecpc->bufFile = fopen(filename, "wb"); - sprintf(filename, "aec_skew%d.dat", webrtc_aec_instance_count); - aecpc->skewFile = fopen(filename, "wb"); - sprintf(filename, "aec_delay%d.dat", webrtc_aec_instance_count); - aecpc->delayFile = fopen(filename, "wb"); - webrtc_aec_instance_count++; - } + aecpc->bufFile = aecpc->skewFile = aecpc->delayFile = NULL; + OpenDebugFiles(aecpc, &webrtc_aec_instance_count); + #endif return 0; @@ -191,9 +186,12 @@ int32_t WebRtcAec_Free(void* aecInst) { #ifdef WEBRTC_AEC_DEBUG_DUMP WebRtc_FreeBuffer(aecpc->far_pre_buf_s16); - fclose(aecpc->bufFile); - fclose(aecpc->skewFile); - fclose(aecpc->delayFile); + if (aecpc->bufFile) { + // we don't let one be open and not the others + fclose(aecpc->bufFile); + fclose(aecpc->skewFile); + fclose(aecpc->delayFile); + } #endif WebRtcAec_FreeAec(aecpc->aec); @@ -439,9 +437,12 @@ int32_t WebRtcAec_Process(void* aecInst, { int16_t far_buf_size_ms = (int16_t)(WebRtcAec_system_delay(aecpc->aec) / (sampMsNb * aecpc->rate_factor)); - (void)fwrite(&far_buf_size_ms, 2, 1, aecpc->bufFile); - (void)fwrite( + OpenDebugFiles(aecpc, &webrtc_aec_instance_count); + if (aecpc->bufFile) { + (void)fwrite(&far_buf_size_ms, 2, 1, aecpc->bufFile); + (void)fwrite( &aecpc->knownDelay, sizeof(aecpc->knownDelay), 1, aecpc->delayFile); + } } #endif @@ -678,7 +679,10 @@ static int ProcessNormal(aecpc_t* aecpc, } #ifdef WEBRTC_AEC_DEBUG_DUMP - (void)fwrite(&aecpc->skew, sizeof(aecpc->skew), 1, aecpc->skewFile); + OpenDebugFiles(aecpc, &webrtc_aec_instance_count); + if (aecpc->skewFile) { + (void)fwrite(&aecpc->skew, sizeof(aecpc->skew), 1, aecpc->skewFile); + } #endif } } @@ -968,3 +972,43 @@ static void EstBufDelayExtended(aecpc_t* self) { self->knownDelay = WEBRTC_SPL_MAX((int)self->filtDelay - 256, 0); } } + +#ifdef WEBRTC_AEC_DEBUG_DUMP +void +OpenDebugFiles(aecpc_t* aecpc, + int *instance_count) +{ + int error = 0; + // XXX If this impacts performance (opening files here), move file open + // to Trace::set_aec_debug(), and just grab them here + if (AECDebug() && !aecpc->bufFile) { + char filename[128]; + sprintf(filename, "aec_buf%d.dat", *instance_count); + aecpc->bufFile = fopen(filename, "wb"); + sprintf(filename, "aec_skew%d.dat", *instance_count); + aecpc->skewFile = fopen(filename, "wb"); + sprintf(filename, "aec_delay%d.dat", *instance_count); + aecpc->delayFile = fopen(filename, "wb"); + + if (!aecpc->bufFile || !aecpc->skewFile || !aecpc->delayFile) { + error = 1; + } else { + (*instance_count)++; + } + } + if (error || + (!AECDebug() && aecpc->bufFile)) { + if (aecpc->bufFile) { + fclose(aecpc->bufFile); + } + if (aecpc->skewFile) { + fclose(aecpc->skewFile); + } + if (aecpc->delayFile) { + fclose(aecpc->delayFile); + } + aecpc->bufFile = aecpc->skewFile = aecpc->delayFile = NULL; + } +} + +#endif diff --git a/media/webrtc/trunk/webrtc/system_wrappers/interface/trace.h b/media/webrtc/trunk/webrtc/system_wrappers/interface/trace.h index 44ea658bdf28..9085680b537f 100644 --- a/media/webrtc/trunk/webrtc/system_wrappers/interface/trace.h +++ b/media/webrtc/trunk/webrtc/system_wrappers/interface/trace.h @@ -54,6 +54,12 @@ class Trace { // Returns what type of messages are written to the trace file. static uint32_t level_filter() { return level_filter_; } + // Enable dumping of AEC inputs and outputs. Can be changed in mid-call + static void set_aec_debug(bool enable) { aec_debug_ = enable; } + static void set_aec_debug_size(uint32_t size) { aec_debug_size_ = size; } + static bool aec_debug() { return aec_debug_; } + static uint32_t aec_debug_size() { return aec_debug_size_; } + // Sets the file name. If add_file_counter is false the same file will be // reused when it fills up. If it's true a new file with incremented name // will be used. @@ -85,8 +91,16 @@ class Trace { private: static uint32_t level_filter_; + static bool aec_debug_; + static uint32_t aec_debug_size_; }; } // namespace webrtc +extern "C" { + extern int AECDebug(); + extern uint32_t AECDebugMaxSize(); + extern void AECDebugEnable(uint32_t enable); +} + #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_H_ diff --git a/media/webrtc/trunk/webrtc/system_wrappers/source/trace_impl.cc b/media/webrtc/trunk/webrtc/system_wrappers/source/trace_impl.cc index 73b5b29b0563..f5b05ac4f5f4 100644 --- a/media/webrtc/trunk/webrtc/system_wrappers/source/trace_impl.cc +++ b/media/webrtc/trunk/webrtc/system_wrappers/source/trace_impl.cc @@ -29,12 +29,20 @@ #pragma warning(disable:4355) #endif // _WIN32 +extern "C" { + int AECDebug() { return (int) webrtc::Trace::aec_debug(); } + uint32_t AECDebugMaxSize() { return webrtc::Trace::aec_debug_size(); } + void AECDebugEnable(uint32_t enable) { webrtc::Trace::set_aec_debug(!!enable); } +} + namespace webrtc { const int Trace::kBoilerplateLength = 71; const int Trace::kTimestampPosition = 13; const int Trace::kTimestampLength = 12; uint32_t Trace::level_filter_ = kTraceDefault; +bool Trace::aec_debug_ = false; +uint32_t Trace::aec_debug_size_ = 4*1024*1024; // Construct On First Use idiom. Avoids "static initialization order fiasco". TraceImpl* TraceImpl::StaticInstance(CountOperation count_operation,