Separate PeerConnection's self-message functions to a new file

This prevents having to have sdp_offer_answer depend on peer_connection
for the messaging functions.

Bug: webrtc:11995
Change-Id: Icad7c9c0e6149bd1b8d78e37eff5f9786b74692e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/186662
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32310}
This commit is contained in:
Harald Alvestrand 2020-10-05 07:01:09 +00:00 committed by Commit Bot
parent 8e4cda7de0
commit 1090e44ac0
8 changed files with 295 additions and 154 deletions

View File

@ -227,6 +227,7 @@ rtc_library("peerconnection") {
deps = [
":dtmf_sender",
":media_stream",
":peer_connection_message_handler",
":rtc_pc_base",
":rtp_receiver",
":rtp_sender",
@ -292,6 +293,21 @@ rtc_library("peerconnection") {
]
}
rtc_library("peer_connection_message_handler") {
sources = [
"peer_connection_message_handler.cc",
"peer_connection_message_handler.h",
]
deps = [
":stats_collector_interface",
"../api:libjingle_peerconnection_api",
"../api:media_stream_interface",
"../api:rtc_error",
"../rtc_base",
"../rtc_base/synchronization:sequence_checker",
]
}
rtc_library("rtp_receiver") {
sources = [
"rtp_receiver.cc",
@ -396,7 +412,10 @@ rtc_library("video_track_source") {
rtc_source_set("stats_collector_interface") {
sources = [ "stats_collector_interface.h" ]
deps = [ "../api:media_stream_interface" ]
deps = [
"../api:libjingle_peerconnection_api",
"../api:media_stream_interface",
]
}
rtc_source_set("libjingle_peerconnection") {

View File

@ -94,42 +94,8 @@ static const char kDefaultVideoSenderId[] = "defaultv0";
// The length of RTCP CNAMEs.
static const int kRtcpCnameLength = 16;
enum {
MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0,
MSG_SET_SESSIONDESCRIPTION_FAILED,
MSG_CREATE_SESSIONDESCRIPTION_FAILED,
MSG_GETSTATS,
MSG_REPORT_USAGE_PATTERN,
};
static const int REPORT_USAGE_PATTERN_DELAY_MS = 60000;
struct SetSessionDescriptionMsg : public rtc::MessageData {
explicit SetSessionDescriptionMsg(
webrtc::SetSessionDescriptionObserver* observer)
: observer(observer) {}
rtc::scoped_refptr<webrtc::SetSessionDescriptionObserver> observer;
RTCError error;
};
struct CreateSessionDescriptionMsg : public rtc::MessageData {
explicit CreateSessionDescriptionMsg(
webrtc::CreateSessionDescriptionObserver* observer)
: observer(observer) {}
rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserver> observer;
RTCError error;
};
struct GetStatsMsg : public rtc::MessageData {
GetStatsMsg(webrtc::StatsObserver* observer,
webrtc::MediaStreamTrackInterface* track)
: observer(observer), track(track) {}
rtc::scoped_refptr<webrtc::StatsObserver> observer;
rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track;
};
// Check if we can send |new_stream| on a PeerConnection.
bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams,
webrtc::MediaStreamInterface* new_stream) {
@ -428,7 +394,8 @@ PeerConnection::PeerConnection(PeerConnectionFactory* factory,
call_(std::move(call)),
call_ptr_(call_.get()),
sdp_handler_(this),
data_channel_controller_(this) {}
data_channel_controller_(this),
message_handler_(signaling_thread()) {}
PeerConnection::~PeerConnection() {
TRACE_EVENT0("webrtc", "PeerConnection::~PeerConnection");
@ -471,23 +438,6 @@ PeerConnection::~PeerConnection() {
// The event log must outlive call (and any other object that uses it).
event_log_.reset();
});
// Process all pending notifications in the message queue. If we don't do
// this, requests will linger and not know they succeeded or failed.
rtc::MessageList list;
signaling_thread()->Clear(this, rtc::MQID_ANY, &list);
for (auto& msg : list) {
if (msg.message_id == MSG_CREATE_SESSIONDESCRIPTION_FAILED) {
// Processing CreateOffer() and CreateAnswer() messages ensures their
// observers are invoked even if the PeerConnection is destroyed early.
OnMessage(&msg);
} else {
// TODO(hbos): Consider processing all pending messages. This would mean
// that SetLocalDescription() and SetRemoteDescription() observers are
// informed of successes and failures; this is currently NOT the case.
delete msg.pdata;
}
}
}
void PeerConnection::DestroyAllChannels() {
@ -729,8 +679,13 @@ bool PeerConnection::Initialize(
}
int delay_ms =
return_histogram_very_quickly_ ? 0 : REPORT_USAGE_PATTERN_DELAY_MS;
signaling_thread()->PostDelayed(RTC_FROM_HERE, delay_ms, this,
MSG_REPORT_USAGE_PATTERN, nullptr);
message_handler_.RequestUsagePatternReport(
[this]() {
RTC_DCHECK_RUN_ON(signaling_thread());
ReportUsagePattern();
},
delay_ms);
if (dependencies.video_bitrate_allocator_factory) {
video_bitrate_allocator_factory_ =
@ -1379,8 +1334,7 @@ bool PeerConnection::GetStats(StatsObserver* observer,
<< track->id();
return false;
}
signaling_thread()->Post(RTC_FROM_HERE, this, MSG_GETSTATS,
new GetStatsMsg(observer, track));
message_handler_.PostGetStats(observer, stats_.get(), track);
return true;
}
@ -2027,48 +1981,6 @@ void PeerConnection::Close() {
observer_ = nullptr;
}
void PeerConnection::OnMessage(rtc::Message* msg) {
RTC_DCHECK_RUN_ON(signaling_thread());
switch (msg->message_id) {
case MSG_SET_SESSIONDESCRIPTION_SUCCESS: {
SetSessionDescriptionMsg* param =
static_cast<SetSessionDescriptionMsg*>(msg->pdata);
param->observer->OnSuccess();
delete param;
break;
}
case MSG_SET_SESSIONDESCRIPTION_FAILED: {
SetSessionDescriptionMsg* param =
static_cast<SetSessionDescriptionMsg*>(msg->pdata);
param->observer->OnFailure(std::move(param->error));
delete param;
break;
}
case MSG_CREATE_SESSIONDESCRIPTION_FAILED: {
CreateSessionDescriptionMsg* param =
static_cast<CreateSessionDescriptionMsg*>(msg->pdata);
param->observer->OnFailure(std::move(param->error));
delete param;
break;
}
case MSG_GETSTATS: {
GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata);
StatsReports reports;
stats_->GetStats(param->track, &reports);
param->observer->OnComplete(reports);
delete param;
break;
}
case MSG_REPORT_USAGE_PATTERN: {
ReportUsagePattern();
break;
}
default:
RTC_NOTREACHED() << "Not implemented";
break;
}
}
cricket::VoiceMediaChannel* PeerConnection::voice_media_channel() const {
RTC_DCHECK(!IsUnifiedPlan());
auto* voice_channel = static_cast<cricket::VoiceChannel*>(
@ -2374,34 +2286,6 @@ void PeerConnection::OnVideoTrackRemoved(VideoTrackInterface* track,
sdp_handler_.UpdateNegotiationNeeded();
}
void PeerConnection::PostSetSessionDescriptionSuccess(
SetSessionDescriptionObserver* observer) {
SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
signaling_thread()->Post(RTC_FROM_HERE, this,
MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg);
}
void PeerConnection::PostSetSessionDescriptionFailure(
SetSessionDescriptionObserver* observer,
RTCError&& error) {
RTC_DCHECK(!error.ok());
SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
msg->error = std::move(error);
signaling_thread()->Post(RTC_FROM_HERE, this,
MSG_SET_SESSIONDESCRIPTION_FAILED, msg);
}
void PeerConnection::PostCreateSessionDescriptionFailure(
CreateSessionDescriptionObserver* observer,
RTCError error) {
RTC_DCHECK(!error.ok());
CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
msg->error = std::move(error);
signaling_thread()->Post(RTC_FROM_HERE, this,
MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg);
}
void PeerConnection::GenerateMediaDescriptionOptions(
const SessionDescriptionInterface* session_desc,
RtpTransceiverDirection audio_direction,
@ -3988,16 +3872,20 @@ void PeerConnection::ClearStatsCache() {
}
}
void PeerConnection::RequestUsagePatternReportForTesting() {
signaling_thread()->Post(RTC_FROM_HERE, this, MSG_REPORT_USAGE_PATTERN,
nullptr);
}
bool PeerConnection::ShouldFireNegotiationNeededEvent(uint32_t event_id) {
RTC_DCHECK_RUN_ON(signaling_thread());
return sdp_handler_.ShouldFireNegotiationNeededEvent(event_id);
}
void PeerConnection::RequestUsagePatternReportForTesting() {
message_handler_.RequestUsagePatternReport(
[this]() {
RTC_DCHECK_RUN_ON(signaling_thread());
ReportUsagePattern();
},
/* delay_ms= */ 0);
}
std::function<void(const rtc::CopyOnWriteBuffer& packet,
int64_t packet_time_us)>
PeerConnection::InitializeRtcpCallback() {

View File

@ -27,6 +27,7 @@
#include "pc/jsep_transport_controller.h"
#include "pc/peer_connection_factory.h"
#include "pc/peer_connection_internal.h"
#include "pc/peer_connection_message_handler.h"
#include "pc/rtc_stats_collector.h"
#include "pc/rtp_sender.h"
#include "pc/rtp_transceiver.h"
@ -67,7 +68,6 @@ class SdpOfferAnswerHandler;
class PeerConnection : public PeerConnectionInternal,
public JsepTransportController::Observer,
public RtpSenderBase::SetStreamsObserver,
public rtc::MessageHandler,
public sigslot::has_slots<> {
public:
// A bit in the usage pattern is registered when its defining event occurs at
@ -367,6 +367,10 @@ class PeerConnection : public PeerConnectionInternal,
RTC_DCHECK_RUN_ON(signaling_thread());
return sctp_mid_s_;
}
PeerConnectionMessageHandler* message_handler() {
RTC_DCHECK_RUN_ON(signaling_thread());
return &message_handler_;
}
// Functions made public for testing.
void ReturnHistogramVeryQuicklyForTesting() {
@ -401,9 +405,6 @@ class PeerConnection : public PeerConnectionInternal,
uint32_t first_ssrc;
};
// Implements MessageHandler.
void OnMessage(rtc::Message* msg) override;
// Plan B helpers for getting the voice/video media channels for the single
// audio/video transceiver, if it exists.
cricket::VoiceMediaChannel* voice_media_channel() const
@ -540,14 +541,6 @@ class PeerConnection : public PeerConnectionInternal,
MediaStreamInterface* stream)
RTC_RUN_ON(signaling_thread());
void PostSetSessionDescriptionSuccess(
SetSessionDescriptionObserver* observer);
void PostSetSessionDescriptionFailure(SetSessionDescriptionObserver* observer,
RTCError&& error);
void PostCreateSessionDescriptionFailure(
CreateSessionDescriptionObserver* observer,
RTCError error);
// Returns the RtpTransceiver, if found, that is associated to the given MID.
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
GetAssociatedTransceiver(const std::string& mid) const;
@ -1003,6 +996,9 @@ class PeerConnection : public PeerConnectionInternal,
video_bitrate_allocator_factory_;
DataChannelController data_channel_controller_;
// Machinery for handling messages posted to oneself
PeerConnectionMessageHandler message_handler_;
};
} // namespace webrtc

View File

@ -0,0 +1,176 @@
/*
* Copyright 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "pc/peer_connection_message_handler.h"
#include <utility>
#include "api/jsep.h"
#include "api/media_stream_interface.h"
#include "api/peer_connection_interface.h"
#include "pc/stats_collector_interface.h"
#include "rtc_base/synchronization/sequence_checker.h"
namespace webrtc {
namespace {
enum {
MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0,
MSG_SET_SESSIONDESCRIPTION_FAILED,
MSG_CREATE_SESSIONDESCRIPTION_FAILED,
MSG_GETSTATS,
MSG_REPORT_USAGE_PATTERN,
};
struct SetSessionDescriptionMsg : public rtc::MessageData {
explicit SetSessionDescriptionMsg(
webrtc::SetSessionDescriptionObserver* observer)
: observer(observer) {}
rtc::scoped_refptr<webrtc::SetSessionDescriptionObserver> observer;
RTCError error;
};
struct CreateSessionDescriptionMsg : public rtc::MessageData {
explicit CreateSessionDescriptionMsg(
webrtc::CreateSessionDescriptionObserver* observer)
: observer(observer) {}
rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserver> observer;
RTCError error;
};
struct GetStatsMsg : public rtc::MessageData {
GetStatsMsg(webrtc::StatsObserver* observer,
StatsCollectorInterface* stats,
webrtc::MediaStreamTrackInterface* track)
: observer(observer), stats(stats), track(track) {}
rtc::scoped_refptr<webrtc::StatsObserver> observer;
StatsCollectorInterface* stats;
rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track;
};
struct RequestUsagePatternMsg : public rtc::MessageData {
explicit RequestUsagePatternMsg(std::function<void()> func)
: function(func) {}
std::function<void()> function;
};
} // namespace
PeerConnectionMessageHandler::~PeerConnectionMessageHandler() {
// Process all pending notifications in the message queue. If we don't do
// this, requests will linger and not know they succeeded or failed.
rtc::MessageList list;
signaling_thread()->Clear(this, rtc::MQID_ANY, &list);
for (auto& msg : list) {
if (msg.message_id == MSG_CREATE_SESSIONDESCRIPTION_FAILED) {
// Processing CreateOffer() and CreateAnswer() messages ensures their
// observers are invoked even if the PeerConnection is destroyed early.
OnMessage(&msg);
} else {
// TODO(hbos): Consider processing all pending messages. This would mean
// that SetLocalDescription() and SetRemoteDescription() observers are
// informed of successes and failures; this is currently NOT the case.
delete msg.pdata;
}
}
}
void PeerConnectionMessageHandler::OnMessage(rtc::Message* msg) {
RTC_DCHECK_RUN_ON(signaling_thread());
switch (msg->message_id) {
case MSG_SET_SESSIONDESCRIPTION_SUCCESS: {
SetSessionDescriptionMsg* param =
static_cast<SetSessionDescriptionMsg*>(msg->pdata);
param->observer->OnSuccess();
delete param;
break;
}
case MSG_SET_SESSIONDESCRIPTION_FAILED: {
SetSessionDescriptionMsg* param =
static_cast<SetSessionDescriptionMsg*>(msg->pdata);
param->observer->OnFailure(std::move(param->error));
delete param;
break;
}
case MSG_CREATE_SESSIONDESCRIPTION_FAILED: {
CreateSessionDescriptionMsg* param =
static_cast<CreateSessionDescriptionMsg*>(msg->pdata);
param->observer->OnFailure(std::move(param->error));
delete param;
break;
}
case MSG_GETSTATS: {
GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata);
StatsReports reports;
param->stats->GetStats(param->track, &reports);
param->observer->OnComplete(reports);
delete param;
break;
}
case MSG_REPORT_USAGE_PATTERN: {
RequestUsagePatternMsg* param =
static_cast<RequestUsagePatternMsg*>(msg->pdata);
param->function();
delete param;
break;
}
default:
RTC_NOTREACHED() << "Not implemented";
break;
}
}
void PeerConnectionMessageHandler::PostSetSessionDescriptionSuccess(
SetSessionDescriptionObserver* observer) {
SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
signaling_thread()->Post(RTC_FROM_HERE, this,
MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg);
}
void PeerConnectionMessageHandler::PostSetSessionDescriptionFailure(
SetSessionDescriptionObserver* observer,
RTCError&& error) {
RTC_DCHECK(!error.ok());
SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
msg->error = std::move(error);
signaling_thread()->Post(RTC_FROM_HERE, this,
MSG_SET_SESSIONDESCRIPTION_FAILED, msg);
}
void PeerConnectionMessageHandler::PostCreateSessionDescriptionFailure(
CreateSessionDescriptionObserver* observer,
RTCError error) {
RTC_DCHECK(!error.ok());
CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
msg->error = std::move(error);
signaling_thread()->Post(RTC_FROM_HERE, this,
MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg);
}
void PeerConnectionMessageHandler::PostGetStats(
StatsObserver* observer,
StatsCollectorInterface* stats,
MediaStreamTrackInterface* track) {
signaling_thread()->Post(RTC_FROM_HERE, this, MSG_GETSTATS,
new GetStatsMsg(observer, stats, track));
}
void PeerConnectionMessageHandler::RequestUsagePatternReport(
std::function<void()> func,
int delay_ms) {
signaling_thread()->PostDelayed(RTC_FROM_HERE, delay_ms, this,
MSG_REPORT_USAGE_PATTERN,
new RequestUsagePatternMsg(func));
}
} // namespace webrtc

View File

@ -0,0 +1,55 @@
/*
* Copyright 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef PC_PEER_CONNECTION_MESSAGE_HANDLER_H_
#define PC_PEER_CONNECTION_MESSAGE_HANDLER_H_
#include "api/rtc_error.h"
#include "api/stats_types.h"
#include "rtc_base/message_handler.h"
#include "rtc_base/thread.h"
namespace webrtc {
class CreateSessionDescriptionObserver;
class SetSessionDescriptionObserver;
class StatsCollectorInterface;
class StatsObserver;
class MediaStreamTrackInterface;
class PeerConnectionMessageHandler : public rtc::MessageHandler {
public:
explicit PeerConnectionMessageHandler(rtc::Thread* signaling_thread)
: signaling_thread_(signaling_thread) {}
~PeerConnectionMessageHandler();
// Implements MessageHandler.
void OnMessage(rtc::Message* msg) override;
void PostSetSessionDescriptionSuccess(
SetSessionDescriptionObserver* observer);
void PostSetSessionDescriptionFailure(SetSessionDescriptionObserver* observer,
RTCError&& error);
void PostCreateSessionDescriptionFailure(
CreateSessionDescriptionObserver* observer,
RTCError error);
void PostGetStats(StatsObserver* observer,
StatsCollectorInterface* stats,
MediaStreamTrackInterface* track);
void RequestUsagePatternReport(std::function<void()>, int delay_ms);
private:
rtc::Thread* signaling_thread() const { return signaling_thread_; }
rtc::Thread* const signaling_thread_;
};
} // namespace webrtc
#endif // PC_PEER_CONNECTION_MESSAGE_HANDLER_H_

View File

@ -17,6 +17,7 @@
#include "api/uma_metrics.h"
#include "pc/media_stream.h"
#include "pc/peer_connection.h"
#include "pc/peer_connection_message_handler.h"
#include "pc/rtp_media_utils.h"
#include "rtc_base/trace_event.h"
#include "system_wrappers/include/metrics.h"
@ -772,10 +773,11 @@ class SdpOfferAnswerHandler::SetSessionDescriptionObserverAdapter
if (!handler_)
return;
if (error.ok()) {
handler_->pc_->PostSetSessionDescriptionSuccess(inner_observer_);
handler_->pc_->message_handler()->PostSetSessionDescriptionSuccess(
inner_observer_);
} else {
handler_->pc_->PostSetSessionDescriptionFailure(inner_observer_,
std::move(error));
handler_->pc_->message_handler()->PostSetSessionDescriptionFailure(
inner_observer_, std::move(error));
}
}
@ -1772,7 +1774,7 @@ void SdpOfferAnswerHandler::DoCreateOffer(
if (pc_->IsClosed()) {
std::string error = "CreateOffer called when PeerConnection is closed.";
RTC_LOG(LS_ERROR) << error;
pc_->PostCreateSessionDescriptionFailure(
pc_->message_handler()->PostCreateSessionDescriptionFailure(
observer, RTCError(RTCErrorType::INVALID_STATE, std::move(error)));
return;
}
@ -1782,7 +1784,7 @@ void SdpOfferAnswerHandler::DoCreateOffer(
if (session_error() != SessionError::kNone) {
std::string error_message = GetSessionErrorMsg();
RTC_LOG(LS_ERROR) << "CreateOffer: " << error_message;
pc_->PostCreateSessionDescriptionFailure(
pc_->message_handler()->PostCreateSessionDescriptionFailure(
observer,
RTCError(RTCErrorType::INTERNAL_ERROR, std::move(error_message)));
return;
@ -1791,7 +1793,7 @@ void SdpOfferAnswerHandler::DoCreateOffer(
if (!ValidateOfferAnswerOptions(options)) {
std::string error = "CreateOffer called with invalid options.";
RTC_LOG(LS_ERROR) << error;
pc_->PostCreateSessionDescriptionFailure(
pc_->message_handler()->PostCreateSessionDescriptionFailure(
observer, RTCError(RTCErrorType::INVALID_PARAMETER, std::move(error)));
return;
}
@ -1801,7 +1803,8 @@ void SdpOfferAnswerHandler::DoCreateOffer(
if (IsUnifiedPlan()) {
RTCError error = HandleLegacyOfferOptions(options);
if (!error.ok()) {
pc_->PostCreateSessionDescriptionFailure(observer, std::move(error));
pc_->message_handler()->PostCreateSessionDescriptionFailure(
observer, std::move(error));
return;
}
}
@ -1856,7 +1859,7 @@ void SdpOfferAnswerHandler::DoCreateAnswer(
if (session_error() != SessionError::kNone) {
std::string error_message = GetSessionErrorMsg();
RTC_LOG(LS_ERROR) << "CreateAnswer: " << error_message;
pc_->PostCreateSessionDescriptionFailure(
pc_->message_handler()->PostCreateSessionDescriptionFailure(
observer,
RTCError(RTCErrorType::INTERNAL_ERROR, std::move(error_message)));
return;
@ -1868,7 +1871,7 @@ void SdpOfferAnswerHandler::DoCreateAnswer(
"PeerConnection cannot create an answer in a state other than "
"have-remote-offer or have-local-pranswer.";
RTC_LOG(LS_ERROR) << error;
pc_->PostCreateSessionDescriptionFailure(
pc_->message_handler()->PostCreateSessionDescriptionFailure(
observer, RTCError(RTCErrorType::INVALID_STATE, std::move(error)));
return;
}

View File

@ -77,7 +77,8 @@ class StatsCollector : public StatsCollectorInterface {
// of filling in |reports|. As is, there's a requirement that the caller
// uses |reports| immediately without allowing any async activity on
// the thread (message handling etc) and then discard the results.
void GetStats(MediaStreamTrackInterface* track, StatsReports* reports);
void GetStats(MediaStreamTrackInterface* track,
StatsReports* reports) override;
// Prepare a local or remote SSRC report for the given ssrc. Used internally
// in the ExtractStatsFromList template.

View File

@ -18,6 +18,7 @@
#include <stdint.h>
#include "api/media_stream_interface.h"
#include "api/stats_types.h"
namespace webrtc {
@ -33,6 +34,8 @@ class StatsCollectorInterface {
// statistics.
virtual void RemoveLocalAudioTrack(AudioTrackInterface* audio_track,
uint32_t ssrc) = 0;
virtual void GetStats(MediaStreamTrackInterface* track,
StatsReports* reports) = 0;
};
} // namespace webrtc