Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Side by Side Diff: talk/media/webrtc/webrtcvoiceengine.cc

Issue 1414743004: Implement AudioSendStream::GetStats(). (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: workaround for android build issue Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * libjingle 2 * libjingle
3 * Copyright 2004 Google Inc. 3 * Copyright 2004 Google Inc.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after
1314 } 1314 }
1315 1315
1316 class WebRtcVoiceMediaChannel::WebRtcAudioSendStream 1316 class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
1317 : public AudioRenderer::Sink { 1317 : public AudioRenderer::Sink {
1318 public: 1318 public:
1319 WebRtcAudioSendStream(int ch, webrtc::AudioTransport* voe_audio_transport, 1319 WebRtcAudioSendStream(int ch, webrtc::AudioTransport* voe_audio_transport,
1320 uint32_t ssrc, webrtc::Call* call) 1320 uint32_t ssrc, webrtc::Call* call)
1321 : channel_(ch), 1321 : channel_(ch),
1322 voe_audio_transport_(voe_audio_transport), 1322 voe_audio_transport_(voe_audio_transport),
1323 call_(call) { 1323 call_(call) {
1324 RTC_DCHECK_GE(ch, 0);
1325 // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore:
1326 // RTC_DCHECK(voe_audio_transport);
1324 RTC_DCHECK(call); 1327 RTC_DCHECK(call);
1328 audio_capture_thread_checker_.DetachFromThread();
1325 webrtc::AudioSendStream::Config config(nullptr); 1329 webrtc::AudioSendStream::Config config(nullptr);
1326 config.voe_channel_id = channel_; 1330 config.voe_channel_id = channel_;
1327 config.rtp.ssrc = ssrc; 1331 config.rtp.ssrc = ssrc;
1328 stream_ = call_->CreateAudioSendStream(config); 1332 stream_ = call_->CreateAudioSendStream(config);
1329 RTC_DCHECK(stream_); 1333 RTC_DCHECK(stream_);
1330 } 1334 }
1331 ~WebRtcAudioSendStream() override { 1335 ~WebRtcAudioSendStream() override {
1336 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
1332 Stop(); 1337 Stop();
1333 call_->DestroyAudioSendStream(stream_); 1338 call_->DestroyAudioSendStream(stream_);
1334 } 1339 }
1335 1340
1336 // Starts the rendering by setting a sink to the renderer to get data 1341 // Starts the rendering by setting a sink to the renderer to get data
1337 // callback. 1342 // callback.
1338 // This method is called on the libjingle worker thread. 1343 // This method is called on the libjingle worker thread.
1339 // TODO(xians): Make sure Start() is called only once. 1344 // TODO(xians): Make sure Start() is called only once.
1340 void Start(AudioRenderer* renderer) { 1345 void Start(AudioRenderer* renderer) {
1341 rtc::CritScope lock(&lock_); 1346 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
1342 RTC_DCHECK(renderer); 1347 RTC_DCHECK(renderer);
1343 if (renderer_) { 1348 if (renderer_) {
1344 RTC_DCHECK(renderer_ == renderer); 1349 RTC_DCHECK(renderer_ == renderer);
1345 return; 1350 return;
1346 } 1351 }
1347 renderer->SetSink(this); 1352 renderer->SetSink(this);
1348 renderer_ = renderer; 1353 renderer_ = renderer;
1349 } 1354 }
1350 1355
1356 webrtc::AudioSendStream::Stats GetStats() const {
1357 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
1358 return stream_->GetStats();
1359 }
1360
1351 // Stops rendering by setting the sink of the renderer to nullptr. No data 1361 // Stops rendering by setting the sink of the renderer to nullptr. No data
1352 // callback will be received after this method. 1362 // callback will be received after this method.
1353 // This method is called on the libjingle worker thread. 1363 // This method is called on the libjingle worker thread.
1354 void Stop() { 1364 void Stop() {
1355 rtc::CritScope lock(&lock_); 1365 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
1356 if (renderer_) { 1366 if (renderer_) {
1357 renderer_->SetSink(nullptr); 1367 renderer_->SetSink(nullptr);
1358 renderer_ = nullptr; 1368 renderer_ = nullptr;
1359 } 1369 }
1360 } 1370 }
1361 1371
1362 // AudioRenderer::Sink implementation. 1372 // AudioRenderer::Sink implementation.
1363 // This method is called on the audio thread. 1373 // This method is called on the audio thread.
1364 void OnData(const void* audio_data, 1374 void OnData(const void* audio_data,
1365 int bits_per_sample, 1375 int bits_per_sample,
1366 int sample_rate, 1376 int sample_rate,
1367 int number_of_channels, 1377 int number_of_channels,
1368 size_t number_of_frames) override { 1378 size_t number_of_frames) override {
1379 RTC_DCHECK(audio_capture_thread_checker_.CalledOnValidThread());
1369 RTC_DCHECK(voe_audio_transport_); 1380 RTC_DCHECK(voe_audio_transport_);
1370 voe_audio_transport_->OnData(channel_, 1381 voe_audio_transport_->OnData(channel_,
1371 audio_data, 1382 audio_data,
1372 bits_per_sample, 1383 bits_per_sample,
1373 sample_rate, 1384 sample_rate,
1374 number_of_channels, 1385 number_of_channels,
1375 number_of_frames); 1386 number_of_frames);
1376 } 1387 }
1377 1388
1378 // Callback from the |renderer_| when it is going away. In case Start() has 1389 // Callback from the |renderer_| when it is going away. In case Start() has
1379 // never been called, this callback won't be triggered. 1390 // never been called, this callback won't be triggered.
1380 void OnClose() override { 1391 void OnClose() override {
1381 rtc::CritScope lock(&lock_); 1392 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
1382 // Set |renderer_| to nullptr to make sure no more callback will get into 1393 // Set |renderer_| to nullptr to make sure no more callback will get into
1383 // the renderer. 1394 // the renderer.
1384 renderer_ = nullptr; 1395 renderer_ = nullptr;
1385 } 1396 }
1386 1397
1387 // Accessor to the VoE channel ID. 1398 // Accessor to the VoE channel ID.
1388 int channel() const { return channel_; } 1399 int channel() const {
1400 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
1401 return channel_;
1402 }
1389 1403
1390 private: 1404 private:
1405 rtc::ThreadChecker signal_thread_checker_;
1406 rtc::ThreadChecker audio_capture_thread_checker_;
1391 const int channel_ = -1; 1407 const int channel_ = -1;
1392 webrtc::AudioTransport* const voe_audio_transport_ = nullptr; 1408 webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
1393 webrtc::Call* call_ = nullptr; 1409 webrtc::Call* call_ = nullptr;
1394 webrtc::AudioSendStream* stream_ = nullptr; 1410 webrtc::AudioSendStream* stream_ = nullptr;
1395 1411
1396 // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler. 1412 // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler.
1397 // PeerConnection will make sure invalidating the pointer before the object 1413 // PeerConnection will make sure invalidating the pointer before the object
1398 // goes away. 1414 // goes away.
1399 AudioRenderer* renderer_ = nullptr; 1415 AudioRenderer* renderer_ = nullptr;
1400 1416
1401 // Protects |renderer_| in Start(), Stop() and OnClose().
1402 rtc::CriticalSection lock_;
1403
1404 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream); 1417 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
1405 }; 1418 };
1406 1419
1407 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { 1420 class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
1408 public: 1421 public:
1409 explicit WebRtcAudioReceiveStream(int voe_channel_id) 1422 explicit WebRtcAudioReceiveStream(int voe_channel_id)
1410 : channel_(voe_channel_id) {} 1423 : channel_(voe_channel_id) {}
1411 1424
1412 int channel() { return channel_; } 1425 int channel() { return channel_; }
1413 1426
(...skipping 12 matching lines...) Expand all
1426 send_bitrate_bps_(0), 1439 send_bitrate_bps_(0),
1427 options_(), 1440 options_(),
1428 dtmf_allowed_(false), 1441 dtmf_allowed_(false),
1429 desired_playout_(false), 1442 desired_playout_(false),
1430 nack_enabled_(false), 1443 nack_enabled_(false),
1431 playout_(false), 1444 playout_(false),
1432 typing_noise_detected_(false), 1445 typing_noise_detected_(false),
1433 desired_send_(SEND_NOTHING), 1446 desired_send_(SEND_NOTHING),
1434 send_(SEND_NOTHING), 1447 send_(SEND_NOTHING),
1435 call_(call) { 1448 call_(call) {
1436 RTC_DCHECK(thread_checker_.CalledOnValidThread());
1437 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel"; 1449 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel";
1438 RTC_DCHECK(nullptr != call); 1450 RTC_DCHECK(nullptr != call);
1439 engine->RegisterChannel(this); 1451 engine->RegisterChannel(this);
1440 SetOptions(options); 1452 SetOptions(options);
1441 } 1453 }
1442 1454
1443 WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() { 1455 WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
1444 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 1456 RTC_DCHECK(thread_checker_.CalledOnValidThread());
1445 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel"; 1457 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel";
1446 1458
(...skipping 1164 matching lines...) Expand 10 before | Expand all | Expand 10 after
2611 << " to bitrate " << bps << " bps" 2623 << " to bitrate " << bps << " bps"
2612 << ", requires at least " << codec.rate << " bps."; 2624 << ", requires at least " << codec.rate << " bps.";
2613 return false; 2625 return false;
2614 } 2626 }
2615 return true; 2627 return true;
2616 } 2628 }
2617 } 2629 }
2618 2630
2619 bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) { 2631 bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
2620 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 2632 RTC_DCHECK(thread_checker_.CalledOnValidThread());
2633 RTC_DCHECK(info);
2621 2634
2622 bool echo_metrics_on = false; 2635 // Get SSRC and stats for each sender.
2623 // These can take on valid negative values, so use the lowest possible level 2636 RTC_DCHECK(info->senders.size() == 0);
2624 // as default rather than -1. 2637 for (const auto& stream : send_streams_) {
2625 int echo_return_loss = -100; 2638 webrtc::AudioSendStream::Stats stats = stream.second->GetStats();
2626 int echo_return_loss_enhancement = -100;
2627 // These can also be negative, but in practice -1 is only used to signal
2628 // insufficient data, since the resolution is limited to multiples of 4 ms.
2629 int echo_delay_median_ms = -1;
2630 int echo_delay_std_ms = -1;
2631 if (engine()->voe()->processing()->GetEcMetricsStatus(
2632 echo_metrics_on) != -1 && echo_metrics_on) {
2633 // TODO(ajm): we may want to use VoECallReport::GetEchoMetricsSummary
2634 // here, but it appears to be unsuitable currently. Revisit after this is
2635 // investigated: http://b/issue?id=5666755
2636 int erl, erle, rerl, anlp;
2637 if (engine()->voe()->processing()->GetEchoMetrics(
2638 erl, erle, rerl, anlp) != -1) {
2639 echo_return_loss = erl;
2640 echo_return_loss_enhancement = erle;
2641 }
2642
2643 int median, std;
2644 float dummy;
2645 if (engine()->voe()->processing()->GetEcDelayMetrics(
2646 median, std, dummy) != -1) {
2647 echo_delay_median_ms = median;
2648 echo_delay_std_ms = std;
2649 }
2650 }
2651
2652 for (const auto& ch : send_streams_) {
2653 const int channel = ch.second->channel();
2654
2655 // Fill in the sender info, based on what we know, and what the
2656 // remote side told us it got from its RTCP report.
2657 VoiceSenderInfo sinfo; 2639 VoiceSenderInfo sinfo;
2658 2640 sinfo.add_ssrc(stats.local_ssrc);
2659 webrtc::CallStatistics cs = {0}; 2641 sinfo.bytes_sent = stats.bytes_sent;
2660 unsigned int ssrc = 0; 2642 sinfo.packets_sent = stats.packets_sent;
2661 if (engine()->voe()->rtp()->GetRTCPStatistics(channel, cs) == -1 || 2643 sinfo.packets_lost = stats.packets_lost;
2662 engine()->voe()->rtp()->GetLocalSSRC(channel, ssrc) == -1) { 2644 sinfo.fraction_lost = stats.fraction_lost;
2663 continue; 2645 sinfo.codec_name = stats.codec_name;
2664 } 2646 sinfo.ext_seqnum = stats.ext_seqnum;
2665 2647 sinfo.jitter_ms = stats.jitter_ms;
2666 sinfo.add_ssrc(ssrc); 2648 sinfo.rtt_ms = stats.rtt_ms;
2667 sinfo.codec_name = send_codec_.get() ? send_codec_->plname : ""; 2649 sinfo.audio_level = stats.audio_level;
2668 sinfo.bytes_sent = cs.bytesSent; 2650 sinfo.aec_quality_min = stats.aec_quality_min;
2669 sinfo.packets_sent = cs.packetsSent; 2651 sinfo.echo_delay_median_ms = stats.echo_delay_median_ms;
2670 // RTT isn't known until a RTCP report is received. Until then, VoiceEngine 2652 sinfo.echo_delay_std_ms = stats.echo_delay_std_ms;
2671 // returns 0 to indicate an error value. 2653 sinfo.echo_return_loss = stats.echo_return_loss;
2672 sinfo.rtt_ms = (cs.rttMs > 0) ? cs.rttMs : -1; 2654 sinfo.echo_return_loss_enhancement = stats.echo_return_loss_enhancement;
2673
2674 // Get data from the last remote RTCP report. Use default values if no data
2675 // available.
2676 sinfo.fraction_lost = -1.0;
2677 sinfo.jitter_ms = -1;
2678 sinfo.packets_lost = -1;
2679 sinfo.ext_seqnum = -1;
2680 std::vector<webrtc::ReportBlock> receive_blocks;
2681 webrtc::CodecInst codec = {0};
2682 if (engine()->voe()->rtp()->GetRemoteRTCPReportBlocks(
2683 channel, &receive_blocks) != -1 &&
2684 engine()->voe()->codec()->GetSendCodec(channel, codec) != -1) {
2685 for (const webrtc::ReportBlock& block : receive_blocks) {
2686 // Lookup report for send ssrc only.
2687 if (block.source_SSRC == sinfo.ssrc()) {
2688 // Convert Q8 to floating point.
2689 sinfo.fraction_lost = static_cast<float>(block.fraction_lost) / 256;
2690 // Convert samples to milliseconds.
2691 if (codec.plfreq / 1000 > 0) {
2692 sinfo.jitter_ms = block.interarrival_jitter / (codec.plfreq / 1000);
2693 }
2694 sinfo.packets_lost = block.cumulative_num_packets_lost;
2695 sinfo.ext_seqnum = block.extended_highest_sequence_number;
2696 break;
2697 }
2698 }
2699 }
2700
2701 // Local speech level.
2702 unsigned int level = 0;
2703 sinfo.audio_level = (engine()->voe()->volume()->
2704 GetSpeechInputLevelFullRange(level) != -1) ? level : -1;
2705
2706 // TODO(xians): We are injecting the same APM logging to all the send
2707 // channels here because there is no good way to know which send channel
2708 // is using the APM. The correct fix is to allow the send channels to have
2709 // their own APM so that we can feed the correct APM logging to different
2710 // send channels. See issue crbug/264611 .
2711 sinfo.echo_return_loss = echo_return_loss;
2712 sinfo.echo_return_loss_enhancement = echo_return_loss_enhancement;
2713 sinfo.echo_delay_median_ms = echo_delay_median_ms;
2714 sinfo.echo_delay_std_ms = echo_delay_std_ms;
2715 // TODO(ajm): Re-enable this metric once we have a reliable implementation.
2716 sinfo.aec_quality_min = -1;
2717 sinfo.typing_noise_detected = typing_noise_detected_; 2655 sinfo.typing_noise_detected = typing_noise_detected_;
2718 2656 // TODO(solenberg): Move to AudioSendStream.
2657 // sinfo.typing_noise_detected = stats.typing_noise_detected;
2719 info->senders.push_back(sinfo); 2658 info->senders.push_back(sinfo);
2720 } 2659 }
2721 2660
2722 // Get the SSRC and stats for each receiver. 2661 // Get SSRC and stats for each receiver.
2723 info->receivers.clear(); 2662 RTC_DCHECK(info->receivers.size() == 0);
2724 for (const auto& stream : receive_streams_) { 2663 for (const auto& stream : receive_streams_) {
2725 webrtc::AudioReceiveStream::Stats stats = stream.second->GetStats(); 2664 webrtc::AudioReceiveStream::Stats stats = stream.second->GetStats();
2726 VoiceReceiverInfo rinfo; 2665 VoiceReceiverInfo rinfo;
2727 rinfo.add_ssrc(stats.remote_ssrc); 2666 rinfo.add_ssrc(stats.remote_ssrc);
2728 rinfo.bytes_rcvd = stats.bytes_rcvd; 2667 rinfo.bytes_rcvd = stats.bytes_rcvd;
2729 rinfo.packets_rcvd = stats.packets_rcvd; 2668 rinfo.packets_rcvd = stats.packets_rcvd;
2730 rinfo.packets_lost = stats.packets_lost; 2669 rinfo.packets_lost = stats.packets_lost;
2731 rinfo.fraction_lost = stats.fraction_lost; 2670 rinfo.fraction_lost = stats.fraction_lost;
2732 rinfo.codec_name = stats.codec_name; 2671 rinfo.codec_name = stats.codec_name;
2733 rinfo.ext_seqnum = stats.ext_seqnum; 2672 rinfo.ext_seqnum = stats.ext_seqnum;
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
2954 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); 2893 LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
2955 return false; 2894 return false;
2956 } 2895 }
2957 } 2896 }
2958 return true; 2897 return true;
2959 } 2898 }
2960 2899
2961 } // namespace cricket 2900 } // namespace cricket
2962 2901
2963 #endif // HAVE_WEBRTC_VOICE 2902 #endif // HAVE_WEBRTC_VOICE
OLDNEW
« no previous file with comments | « talk/media/webrtc/fakewebrtcvoiceengine.h ('k') | talk/media/webrtc/webrtcvoiceengine_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698