Advertisement
JeeDjii

WebRTC Impl

Jul 6th, 2016
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 18.30 KB | None | 0 0
  1. #include "WebRTC_DirectFilter.h"
  2. #include "Exception.h"
  3. #include "chronometer.h"
  4.  
  5.     WebRTC_DirectFilter::WebRTC_DirectFilter()
  6.     {
  7.         is_initialized = false;
  8.         audioframe_counter = 0;
  9.         statistics_display_counter = 0;
  10.  
  11.         component_enabled = false;
  12.  
  13.         io_embargo = false;
  14.         disposed = false;
  15.         disposing = false;
  16.  
  17.         EnableFilterDebugLog(true);
  18.  
  19.     }
  20.  
  21.  
  22.     WebRTC_DirectFilter::~WebRTC_DirectFilter()
  23.     {
  24.         if (disposed || disposing) return;
  25.  
  26.         Dispose();
  27.     }
  28.  
  29.     bool WebRTC_DirectFilter::Initialize(AudioChannels channel_config, bool enableDelayAgnoticism = false, bool enableSuperAEC = false)
  30.     {
  31.         Config config;
  32.         if (enableDelayAgnoticism) {
  33.             config.Set<DelayAgnostic>(new DelayAgnostic(true));
  34.             Log(FLV_Framework::LOG_INFO, LOG << "Delay Agnostic activated.");
  35.         }
  36.         if (enableSuperAEC) {
  37.             config.Set<ExtendedFilter>(new ExtendedFilter(true));
  38.             Log(FLV_Framework::LOG_INFO, LOG << "Extended Filter activated.");
  39.         }
  40.  
  41.         return this->Initialize(channel_config, config);
  42.     }
  43.  
  44.     // If not initialized, the APM object will be created
  45.     // But is he was already created, only the config will be applied
  46.     // (Some configuration could not be applied when apm is already created,
  47.     // call Dispose() then Initialize to force the reinstanciation)
  48.     bool WebRTC_DirectFilter::Initialize(AudioChannels channel_config, Config& config)
  49.     {
  50.         try
  51.         {
  52.             ulock lock(apm_mutex);
  53.  
  54.             channels = channel_config;
  55.  
  56.             // Only if it's the first time, 1st step
  57.             if(is_initialized == false) {
  58.                 apm.release();
  59.                 apm.reset(AudioProcessing::Create(config));
  60.             }
  61.  
  62.             ResetClockDrift();
  63.  
  64.             apm->Initialize((int)channels.input.sample_rate, (int)channels.input.sample_rate, (int)channels.reverse.sample_rate,
  65.                     channels.input.channel_layout, channels.output.channel_layout, channels.reverse.channel_layout);
  66.  
  67.             apm->echo_cancellation()->enable_drift_compensation(true);
  68.  
  69.             apm->voice_detection()->Enable(true);
  70.             apm->voice_detection()->set_likelihood(VoiceDetection::kModerateLikelihood);
  71.  
  72.             if(is_initialized == true) { // Only if it's already initialized
  73.                 apm->SetExtraOptions(config);
  74.             }
  75.  
  76.             // Only if it's the first time, Last Step !
  77.             // Needed to be called after the initialize
  78.             if(is_initialized == false) {              
  79. #if defined(_FILTER_DEBUG) && defined(_WIN32)
  80.                 reverse_file.Open("__reverse.wav", channels.reverse.sample_rate, channels.reverse.GetNumberOfChannels());
  81.                 process_file.Open("__process.wav", channels.input.sample_rate, channels.input.GetNumberOfChannels());
  82.                 out_file.Open("__out.wav", channels.output.sample_rate, channels.output.GetNumberOfChannels());
  83.                 out_nodebug_file.Open("__out_nodebug.wav", channels.output.sample_rate, channels.output.GetNumberOfChannels());
  84.  
  85.                 apm->StartDebugRecording("DebugRecording", 0);
  86. #endif
  87.  
  88. #ifdef __AECM_STORAGE
  89.                 ecp_storage.LoadFromStorage(false);
  90. #endif
  91.  
  92.                 Log(LOG_VERBOSE, "Audio Filter initialized.");
  93.  
  94.                 is_initialized = true; // we are correctly initialized
  95.             }
  96.  
  97.             lock.unlock();
  98.         }
  99.         catch (std::exception &e) {
  100.             Log(FLV_Framework::LOG_ERROR, LOG << "An exception occured when initializing Filter. (" << e.what() << ")");
  101.         }
  102.         catch (...) {
  103.             Log(FLV_Framework::LOG_ERROR, LOG << "An unknow exception occured when initializing Filter.");
  104.         }
  105.  
  106.         return is_initialized;
  107.     }
  108.  
  109.     bool WebRTC_DirectFilter::Dispose() {
  110.         if (disposing || disposed) return false;
  111.         disposing = true;
  112.  
  113.         is_initialized = false;
  114.         io_embargo = true;
  115.  
  116.         ulock lock(apm_mutex);
  117.        
  118. #ifdef __AECM_STORAGE
  119.         try {
  120.             // saving first the echo_path if the is any to save
  121.             if (apm->echo_control_mobile()->is_enabled()) {
  122.                 long size = apm->echo_control_mobile()->echo_path_size_bytes();
  123.                 std::shared_ptr<byte> data(new byte[size]);
  124.                 apm->echo_control_mobile()->GetEchoPath(data.get(), size);
  125.                 ecp_storage.Set(mode_echo_mobile, data, size);
  126.             }
  127.         }
  128.         catch (std::exception& ex) {
  129.             Log(FLV_Framework::LOG_ERROR, LOG << "Couldn't register echo path : " << ex.what());
  130.         }
  131. #endif     
  132.  
  133.  
  134.         if (apm) {
  135. #ifdef _FILTER_DEBUG
  136.             apm->StopDebugRecording();
  137. #endif
  138.             delete apm.release(); // delete apm
  139.         }
  140.         lock.unlock();
  141.  
  142. #if defined(_WIN32)
  143.         reverse_file.Close();
  144.         process_file.Close();
  145.         out_file.Close();
  146.         out_nodebug_file.Close();
  147. #endif
  148.  
  149.         //detection.Dispose();
  150.  
  151.         disposed = true;
  152.         disposing = false;
  153.         Log(FLV_Framework::LOG_VERBOSE, LOG << "Filter fully disposed.");
  154.         return true;
  155.     }
  156.  
  157.     // The delay expressed here is the delay between the speaker and the microphone in the library (and not the internet delay).
  158.     void WebRTC_DirectFilter::SetDelay(uint16 delay)
  159.     {
  160.         if (IsReady() == false) return;
  161.  
  162.         ulock lock(apm_mutex);
  163.         apm->set_stream_delay_ms(delay);
  164.     }
  165.  
  166.     void WebRTC_DirectFilter::SetLogger(std::function<void(FLV_Framework::LogLevel, std::string)> loggerFunction)
  167.     {
  168.         LoggerClass::SetLogger(loggerFunction);
  169.  
  170. #ifdef __AECM_STORAGE
  171.         ecp_storage.SetLogger(loggerFunction);
  172. #endif
  173.     }
  174.  
  175.  
  176.     void WebRTC_DirectFilter::AecLog(FLV_Framework::LogLevel logLevel, std::string message)
  177.     {
  178.         if (enable_aec_log) Log(logLevel, message);
  179.     }
  180.  
  181.     bool WebRTC_DirectFilter::EnableAEC(bool enable, bool useV3, bool useRefinedFilter) {
  182.         if (IsReady() == false) return false;
  183.  
  184.         ulock lock(apm_mutex);
  185.         if (enable && apm->echo_control_mobile()->is_enabled())
  186.             EnableMobileAEC(false);
  187.  
  188. #ifndef OSX // OSX don't support that (until we can use FLVFramework for 64 bits on osx)
  189.         if(enable) // set aec v3 only if we activate aec
  190.         {
  191.             Config c;
  192.             c.Set<EchoCanceller3>(new EchoCanceller3(useV3));
  193.             c.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(useRefinedFilter));
  194.             apm->SetExtraOptions(c);
  195.  
  196.         }
  197. #endif
  198.  
  199.         apm->echo_cancellation()->Enable(enable);
  200.         if (enable)
  201.         {
  202.             if (apm->echo_cancellation()->is_delay_logging_enabled() == false) {
  203.                 apm->echo_cancellation()->enable_metrics(true);
  204.                 apm->echo_cancellation()->enable_delay_logging(true);
  205.             }
  206.  
  207.             Log(FLV_Framework::LOG_INFO, LOG << "Echo Cancellation activated.");
  208.         }
  209.         else
  210.         {
  211.             Log(FLV_Framework::LOG_INFO, LOG << "Echo Cancellation desactivated.");
  212.         }
  213.         lock.unlock();
  214.  
  215.         return true;
  216.     }
  217.  
  218.     //TODO : Save an Echo path, and restore it
  219.     bool WebRTC_DirectFilter::EnableMobileAEC(bool enable)
  220.     {
  221.         if (IsReady() == false) return false;
  222.  
  223.         if (enable && IsAEC())
  224.             EnableAEC(false);
  225.  
  226.         ulock lock(apm_mutex);
  227.         apm->echo_control_mobile()->Enable(enable);
  228.         lock.unlock();
  229.  
  230.         if (enable)
  231.         {
  232.             Log(FLV_Framework::LOG_INFO, LOG << "Mobile Echo Cancellation activated.");
  233.         }
  234.         else
  235.         {
  236.             Log(FLV_Framework::LOG_INFO, LOG << "Mobile Echo Cancellation desactivated.");
  237.         }
  238.  
  239.         SetDelay(0);
  240.  
  241.         return true;
  242.     }
  243.  
  244.     bool WebRTC_DirectFilter::SetMobileAECMode(EnumEchoCancellationMobileMode mode)
  245.     {
  246.         if (IsReady() == false) return false;
  247.  
  248.         EchoControlMobile::RoutingMode mode_filter;
  249.         switch (mode)
  250.         {
  251.         case QuietEarpieceOrHeadset:
  252.             mode_filter = EchoControlMobile::kQuietEarpieceOrHeadset;
  253.             break;
  254.         case Earpiece:
  255.             mode_filter = EchoControlMobile::kEarpiece;
  256.             break;
  257.         case LoudEarpiece:
  258.             mode_filter = EchoControlMobile::kLoudEarpiece;
  259.             break;
  260.         case Speakerphone:
  261.             mode_filter = EchoControlMobile::kSpeakerphone;
  262.             break;
  263.         case LoudSpeakerphone:
  264.             mode_filter = EchoControlMobile::kLoudSpeakerphone;
  265.             break;
  266.         default:
  267.             mode_filter = EchoControlMobile::kLoudEarpiece;
  268.             break;
  269.         }
  270.  
  271.         ulock lock(apm_mutex);
  272.         mode_echo_mobile = mode;
  273.         apm->echo_control_mobile()->set_routing_mode(mode_filter);
  274.        
  275. #ifdef __AECM_STORAGE
  276.         std::shared_ptr<WebRTC_EchoPathFile> ecp = ecp_storage.Get(mode);
  277.         if (ecp != nullptr) {
  278.             // If the size is different, we are not in the same situation, we erase the ecp file and bypass any SetEchoPath
  279.             if (ecp->GetSize() != apm->echo_control_mobile()->echo_path_size_bytes()) {
  280.                 ecp_storage.Clear(mode);
  281.                 Log(FLV_Framework::LOG_VERBOSE, LOG << "Echo Path for " << static_cast<int>(mode) << " route mode is cleared.");
  282.             } else {
  283.                 apm->echo_control_mobile()->SetEchoPath(ecp->GetData().get(), ecp->GetSize());
  284.                 Log(FLV_Framework::LOG_VERBOSE, LOG << "Echo Path for " << static_cast<int>(mode) << " route mode is set.");
  285.             }
  286.         }
  287. #endif
  288.         lock.unlock();
  289.  
  290.         Log(FLV_Framework::LOG_INFO, LOG << "Mobile Echo Cancellation level set to " << mode_filter << ".");
  291.  
  292.         return true;
  293.     }
  294.  
  295.     bool WebRTC_DirectFilter::SetAECLevel(EnumFilterLevel lvl) {
  296.         if (IsReady() == false) return false;
  297.  
  298.         EchoCancellation::SuppressionLevel lvl_filter;
  299.         switch (lvl)
  300.         {
  301.         case VeryHigh:
  302.         case High:
  303.             lvl_filter = EchoCancellation::kHighSuppression;
  304.             break;
  305.         case Moderate:
  306.             lvl_filter = EchoCancellation::kModerateSuppression;
  307.             break;
  308.         case Low:
  309.             lvl_filter = EchoCancellation::kLowSuppression;
  310.             break;
  311.         default:
  312.             lvl_filter = EchoCancellation::kModerateSuppression;
  313.             break;
  314.         }
  315.  
  316.         ulock lock(apm_mutex);
  317.         apm->echo_cancellation()->set_suppression_level(lvl_filter);
  318.         lock.unlock();
  319.  
  320.         Log(FLV_Framework::LOG_INFO, LOG << "Echo Cancellation level set to " << lvl_filter << ".");
  321.  
  322.         return true;
  323.     }
  324.  
  325.     bool WebRTC_DirectFilter::EnableNoiseSuppression(bool enable)
  326.     {
  327.         if (IsReady() == false) return false;
  328.  
  329.         ulock lock(apm_mutex);
  330.         apm->noise_suppression()->Enable(enable);
  331.         lock.unlock();
  332.  
  333.         if (enable)
  334.         {
  335.             Log(FLV_Framework::LOG_INFO, LOG << "Noise suppression activated.");
  336.         }
  337.         else
  338.         {
  339.             Log(FLV_Framework::LOG_INFO, LOG << "Noise suppression desactivated.");
  340.         }
  341.  
  342.         return true;
  343.     }
  344.     bool WebRTC_DirectFilter::SetNoiseSuppressionLevel(EnumFilterLevel lvl)
  345.     {
  346.         if (IsReady() == false) return false;
  347.  
  348.         NoiseSuppression::Level lvlNoise;
  349.         switch (lvl)
  350.         {
  351.         case VeryHigh:
  352.             lvlNoise = NoiseSuppression::kVeryHigh;
  353.             break;
  354.         case High:
  355.             lvlNoise = NoiseSuppression::kHigh;
  356.             break;
  357.         case Moderate:
  358.             lvlNoise = NoiseSuppression::kModerate;
  359.             break;
  360.         case Low:
  361.             lvlNoise = NoiseSuppression::kLow;
  362.             break;
  363.         default:
  364.             lvlNoise = NoiseSuppression::kHigh;
  365.             break;
  366.         }
  367.  
  368.         ulock lock(apm_mutex);
  369.         apm->noise_suppression()->set_level(lvlNoise);
  370.         lock.unlock();
  371.  
  372.         Log(FLV_Framework::LOG_INFO, LOG << "Noise suppression level set to " << lvlNoise << ".");
  373.  
  374.         return true;
  375.     }
  376.  
  377.     bool WebRTC_DirectFilter::EnableAutomaticGainControl(bool enable, bool withLimiter)
  378.     {
  379.         if (IsReady() == false) return false;
  380.  
  381.         ulock lock(apm_mutex);
  382.         apm->gain_control()->Enable(enable);
  383.         apm->gain_control()->enable_limiter(withLimiter);
  384.         lock.unlock();
  385.  
  386.         if (enable)
  387.         {
  388.             Log(FLV_Framework::LOG_INFO, LOG << "Automatic gain control activated.");
  389.         }
  390.         else
  391.         {
  392.             Log(FLV_Framework::LOG_INFO, LOG << "Automatic gain control desactivated.");
  393.         }
  394.  
  395.         return true;
  396.     }
  397.  
  398.     bool WebRTC_DirectFilter::SetAGCLevel(int level, int compressionGain)
  399.     {
  400.         if (IsReady() == false) return false;
  401.  
  402.         ulock lock(apm_mutex);
  403.         apm->gain_control()->set_target_level_dbfs(level);
  404.         apm->gain_control()->set_compression_gain_db(compressionGain);
  405.         lock.unlock();
  406.  
  407.         Log(FLV_Framework::LOG_INFO, LOG << "AGC level set to " << level << " dbfs and " << compressionGain << "db for compression gain.");
  408.  
  409.         return true;
  410.     }
  411.  
  412.     bool WebRTC_DirectFilter::EnableHighPassFilter(bool enable)
  413.     {
  414.         if (IsReady() == false) return false;
  415.  
  416.         ulock lock(apm_mutex);
  417.         apm->high_pass_filter()->Enable(enable);
  418.         lock.unlock();
  419.  
  420.         if (enable)
  421.         {
  422.             Log(FLV_Framework::LOG_INFO, LOG << "High pass filter activated.");
  423.         }
  424.         else
  425.         {
  426.             Log(FLV_Framework::LOG_INFO, LOG << "High pass filter desactivated.");
  427.         }
  428.  
  429.         return true;
  430.     }
  431.  
  432.     // Don't work for Mobile AEC (AECM)
  433.     bool WebRTC_DirectFilter::EnableDelayAgnosticism(bool enable)
  434.     {
  435.         if (IsReady() == false) return false;
  436.  
  437.         Config c;
  438.         c.Set<DelayAgnostic>(new DelayAgnostic(enable));
  439.  
  440.         ulock lock(apm_mutex);
  441.         apm->SetExtraOptions(c);
  442.         lock.unlock();
  443.         SetDelay(0);
  444.  
  445.         if (enable)
  446.         {
  447.             Log(FLV_Framework::LOG_INFO, LOG << "Delay agnosticism activated.");
  448.         }
  449.         else
  450.         {
  451.             Log(FLV_Framework::LOG_INFO, LOG << "Delay agnosticism desactivated.");
  452.         }
  453.  
  454.         return true;
  455.     }
  456.  
  457.     bool WebRTC_DirectFilter::EnableIntelligibilityEnhancement(bool enable)
  458.     {
  459.         if (IsReady() == false) return false;
  460.  
  461.         Config c;
  462.         c.Set<Intelligibility>(new Intelligibility(enable));
  463.  
  464.         ulock lock(apm_mutex);
  465.         apm->SetExtraOptions(c);
  466.         lock.unlock();
  467.  
  468.         if (enable)
  469.         {
  470.             Log(FLV_Framework::LOG_INFO, LOG << "Intelligibility enhancement activated.");
  471.         }
  472.         else
  473.         {
  474.             Log(FLV_Framework::LOG_INFO, LOG << "Intelligibility enhancement desactivated.");
  475.         }
  476.  
  477.         return true;
  478.     }
  479.  
  480.     // Be careful, extend filter is more complex, it can add 25% of charge on the actual process.
  481.     bool WebRTC_DirectFilter::EnableAECExtendedFilter(bool enable)
  482.     {
  483.         if (IsReady() == false) return false;
  484.  
  485.         Config c;
  486.         c.Set<ExtendedFilter>(new ExtendedFilter(enable));
  487.  
  488.         ulock lock(apm_mutex);
  489.         apm->SetExtraOptions(c);
  490.         lock.unlock();
  491.  
  492.         if (enable)
  493.         {
  494.             Log(FLV_Framework::LOG_INFO, LOG << "Extend Filter activated.");
  495.         }
  496.         else
  497.         {
  498.             Log(FLV_Framework::LOG_INFO, LOG << "Extend Filter desactivated.");
  499.         }
  500.  
  501.         return true;
  502.     }
  503.     bool WebRTC_DirectFilter::IsAEC() {
  504.         if (IsReady() == false) return false;
  505.  
  506.         ulock lock(apm_mutex);
  507.         return apm->echo_cancellation()->is_enabled();
  508.     }
  509.  
  510.     void WebRTC_DirectFilter::ReverseStream(ShFLVDataFrame_Internal frame)
  511.     {
  512.         // if io_embargo, we ignore the frame
  513.         if (IsReady() == false || io_embargo || component_enabled == false) return;
  514.         try
  515.         {
  516.             ulock slock(apm_mutex);
  517.             apm->ProcessReverseStream(frame->GetAudioFrame());
  518.             slock.unlock();
  519.             _playedSamples += frame->GetCount();
  520.             last_speaker_delay = (int)frame->GetDelayCalculator().GetRenderDelay();
  521.         }
  522.         catch (std::exception& ex)
  523.         {
  524.             Log(FLV_Framework::LOG_ERROR, LOG << "An exception occured when enqueuing Analyze queue : " << ex.what());
  525.         }
  526.         catch (...)
  527.         {
  528.             Log(FLV_Framework::LOG_ERROR, LOG << "An unknow exception occured when enqueuing Analyze queue.");
  529.         }
  530.     }
  531.  
  532.     bool WebRTC_DirectFilter::ProcessStream(ShFLVDataFrame_Internal frame)
  533.     {
  534.         return false;
  535.     }
  536.  
  537.     void WebRTC_DirectFilter::UpdateAudioConfiguration(const AudioChannels _channels)
  538.     {
  539.         if (is_initialized == false) return; // just update
  540.         Config config;
  541.         Initialize(_channels, config);
  542.     }
  543.  
  544.     bool WebRTC_DirectFilter::ProcessStream(ShFLVDataFrame_Internal frame, ShFLVDataFrame_Internal& out_frame)
  545.     {
  546.         // if io_embargo, we ignore the frame
  547.         if (IsReady() == false || io_embargo || component_enabled == false) return false; // is not ready we return
  548.  
  549.         bool ok_process = false;
  550.         try
  551.         {
  552.             DelayCalculator d = frame->GetDelayCalculator();
  553.             d.SetRenderDelay(last_speaker_delay);
  554.  
  555.             _recSamples += frame->GetCount();
  556.  
  557.             ulock slock(apm_mutex);
  558.             int32_t drift = GetClockDrift(_playedSamples, _recSamples);
  559.             apm->echo_cancellation()->set_stream_drift_samples(drift);
  560.             apm->set_stream_delay_ms(static_cast<int>(d.GetDelay()));
  561.             //ShFLVDataFrame_Internal out = resampler_process.Resample(frame);
  562.             ShFLVDataFrame_Internal out(new FLVDataFrame_Internal((*frame.get()))); // cpy
  563.  
  564.             int err = apm->ProcessStream(out->GetAudioFrame());
  565.  
  566.             slock.unlock();
  567.  
  568.             if (err == 0) {
  569.                 out_frame = out;
  570.                 ok_process = true;
  571.             }
  572.            
  573.             if (statistics_display_counter > 100) {
  574.                 DisplayDebugInfo(&d);
  575.                 statistics_display_counter = 0;
  576.             }
  577.             statistics_display_counter++;
  578.  
  579.         }
  580.         catch (std::exception& ex)
  581.         {
  582.             Log(FLV_Framework::LOG_ERROR, LOG << "An exception occured when enqueuing Process queue : " << ex.what());
  583.             ok_process = false;
  584.             out_frame.reset();
  585.         }
  586.         catch (...)
  587.         {
  588.             Log(FLV_Framework::LOG_ERROR, LOG << "An unknow exception occured when enqueuing Process queue.");
  589.             ok_process = false;
  590.             out_frame.reset();
  591.         }
  592.  
  593.         return ok_process;
  594.     }
  595.  
  596.     int32_t WebRTC_DirectFilter::GetClockDrift(const uint32_t plSamp, const uint32_t rcSamp)
  597.     {
  598.         int drift = 0;
  599.         unsigned int plSampDiff = 0, rcSampDiff = 0;
  600.  
  601.         if (plSamp >= _plSampOld)
  602.         {
  603.             plSampDiff = plSamp - _plSampOld;
  604.         }
  605.         else
  606.         {
  607.             // Wrap
  608.             int i = 31;
  609.             while (_plSampOld <= (unsigned int)std::pow(i, 2))
  610.             {
  611.                 i--;
  612.             }
  613.  
  614.             // Add the amount remaining prior to wrapping
  615.             plSampDiff = plSamp + (unsigned int)std::pow(i + 1, 2) - _plSampOld;
  616.         }
  617.  
  618.         if (rcSamp >= _rcSampOld)
  619.         {
  620.             rcSampDiff = rcSamp - _rcSampOld;
  621.         }
  622.         else
  623.         {   // Wrap
  624.             int i = 31;
  625.             while (_rcSampOld <= (unsigned int)std::pow(i, 2))
  626.             {
  627.                 i--;
  628.             }
  629.  
  630.             rcSampDiff = rcSamp + (unsigned int)std::pow(i + 1, 2) - _rcSampOld;
  631.         }
  632.  
  633.         drift = plSampDiff - rcSampDiff;
  634.  
  635.         _plSampOld = plSamp;
  636.         _rcSampOld = rcSamp;
  637.  
  638.         return drift;
  639.     }
  640.  
  641.     void WebRTC_DirectFilter::DisplayDebugInfo(DelayCalculator* delay_calculator)
  642.     {
  643.         if (IsReady() == false) return;
  644.  
  645.         ulock lock(apm_mutex);
  646.         try {
  647.  
  648.             EchoCancellation::Metrics echo_metrics;
  649.             apm->echo_cancellation()->GetMetrics(&echo_metrics);
  650.  
  651.             int median = 0;
  652.             int std = 0;
  653.             float fraction_poor_delays = 0;
  654.             apm->echo_cancellation()->GetDelayMetrics(&median, &std, &fraction_poor_delays);
  655.  
  656.             int drift = apm->echo_cancellation()->stream_drift_samples();
  657.  
  658.             int delay = 0;
  659.             int delay_apm = apm->stream_delay_ms();
  660.             if (delay_calculator != nullptr) {
  661.                 delay = (delay_calculator->GetDelay() == DELAY_CALCULATOR_ERROR ? -1 : static_cast<int>(delay_calculator->GetDelay()));
  662.             }
  663.  
  664.             std::string ss = LOG << "[Filter] "
  665.                 << "Delay(d" << delay << ",apm" << delay_apm << ",drift" << drift << ") "
  666.                 << "HasEcho(" << apm->echo_cancellation()->stream_has_echo() << ") "
  667.                 << "HasVoice(" << apm->voice_detection()->stream_has_voice() << ") "
  668.                 << "MetricsINST(" << echo_metrics.a_nlp.instant << "," << echo_metrics.echo_return_loss.instant << "," << echo_metrics.echo_return_loss_enhancement.instant << "," << echo_metrics.residual_echo_return_loss.instant << ") "
  669.                 << "MetricsAVG(" << echo_metrics.a_nlp.average << "," << echo_metrics.echo_return_loss.average << "," << echo_metrics.echo_return_loss_enhancement.average << "," << echo_metrics.residual_echo_return_loss.average << ") "
  670.                 << "DelayMetrics(" << median << "," << std << "," << fraction_poor_delays << ")";
  671.             AecLog(FLV_Framework::LOG_DEBUG, ss);
  672.         }
  673.         catch (std::exception& ex) {
  674.             Log(FLV_Framework::LOG_ERROR, LOG << "An exception occured when logging large filter debug. " << ex.what());
  675.         }
  676.         catch (...) {
  677.             Log(FLV_Framework::LOG_ERROR, "An unknow exception occured when logging large filter debug.");
  678.         }
  679.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement