Update libjingle 62364298->62472237
git-svn-id: http://webrtc.googlecode.com/svn/trunk@5632 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
1bbfb57d71
commit
40b3b68cdf
@ -41,17 +41,21 @@ class AudioTrack : public MediaStreamTrack<AudioTrackInterface> {
|
||||
static talk_base::scoped_refptr<AudioTrack> Create(
|
||||
const std::string& id, AudioSourceInterface* source);
|
||||
|
||||
virtual AudioSourceInterface* GetSource() const {
|
||||
// AudioTrackInterface implementation.
|
||||
virtual AudioSourceInterface* GetSource() const OVERRIDE {
|
||||
return audio_source_.get();
|
||||
}
|
||||
|
||||
// This method is used for supporting multiple sources/sinks for AudioTracks.
|
||||
virtual cricket::AudioRenderer* GetRenderer() {
|
||||
// TODO(xians): Implement these methods.
|
||||
virtual void AddSink(AudioTrackSinkInterface* sink) OVERRIDE {}
|
||||
virtual void RemoveSink(AudioTrackSinkInterface* sink) OVERRIDE {}
|
||||
virtual bool GetSignalLevel(int* level) OVERRIDE { return false; }
|
||||
virtual AudioProcessorInterface* GetAudioProcessor() OVERRIDE { return NULL; }
|
||||
virtual cricket::AudioRenderer* GetRenderer() OVERRIDE {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Implement MediaStreamTrack
|
||||
virtual std::string kind() const;
|
||||
// MediaStreamTrack implementation.
|
||||
virtual std::string kind() const OVERRIDE;
|
||||
|
||||
protected:
|
||||
AudioTrack(const std::string& label, AudioSourceInterface* audio_source);
|
||||
|
@ -174,18 +174,55 @@ class AudioTrackSinkInterface {
|
||||
virtual ~AudioTrackSinkInterface() {}
|
||||
};
|
||||
|
||||
// Interface of the audio processor used by the audio track to collect
|
||||
// statistics.
|
||||
class AudioProcessorInterface : public talk_base::RefCountInterface {
|
||||
public:
|
||||
struct AudioProcessorStats {
|
||||
AudioProcessorStats() : typing_noise_detected(false),
|
||||
echo_return_loss(0),
|
||||
echo_return_loss_enhancement(0),
|
||||
echo_delay_median_ms(0),
|
||||
aec_quality_min(0.0),
|
||||
echo_delay_std_ms(0) {}
|
||||
~AudioProcessorStats() {}
|
||||
|
||||
bool typing_noise_detected;
|
||||
int echo_return_loss;
|
||||
int echo_return_loss_enhancement;
|
||||
int echo_delay_median_ms;
|
||||
float aec_quality_min;
|
||||
int echo_delay_std_ms;
|
||||
};
|
||||
|
||||
// Get audio processor statistics.
|
||||
virtual void GetStats(AudioProcessorStats* stats) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~AudioProcessorInterface() {}
|
||||
};
|
||||
|
||||
class AudioTrackInterface : public MediaStreamTrackInterface {
|
||||
public:
|
||||
// TODO(xians): Figure out if the following interface should be const or not.
|
||||
virtual AudioSourceInterface* GetSource() const = 0;
|
||||
|
||||
// Adds/Removes a sink that will receive the audio data from the track.
|
||||
// TODO(xians): Make them pure virtual after Chrome implements these
|
||||
// interfaces.
|
||||
virtual void AddSink(AudioTrackSinkInterface* sink) {}
|
||||
virtual void RemoveSink(AudioTrackSinkInterface* sink) {}
|
||||
// Add/Remove a sink that will receive the audio data from the track.
|
||||
virtual void AddSink(AudioTrackSinkInterface* sink) = 0;
|
||||
virtual void RemoveSink(AudioTrackSinkInterface* sink) = 0;
|
||||
|
||||
// Gets a pointer to the audio renderer of this AudioTrack.
|
||||
// Get the signal level from the audio track.
|
||||
// Return true on success, otherwise false.
|
||||
// TODO(xians): Change the interface to int GetSignalLevel() and pure virtual
|
||||
// after Chrome has the correct implementation of the interface.
|
||||
virtual bool GetSignalLevel(int* level) { return false; }
|
||||
|
||||
// Get the audio processor used by the audio track. Return NULL if the track
|
||||
// does not have any processor.
|
||||
// TODO(xians): Make the interface pure virtual.
|
||||
virtual AudioProcessorInterface* GetAudioProcessor() { return NULL; }
|
||||
|
||||
// Get a pointer to the audio renderer of this AudioTrack.
|
||||
// The pointer is valid for the lifetime of this AudioTrack.
|
||||
// TODO(xians): Remove the following interface after Chrome switches to
|
||||
// AddSink() and RemoveSink() interfaces.
|
||||
|
@ -321,8 +321,29 @@ bool MediaStreamSignaling::AddLocalStream(MediaStreamInterface* local_stream) {
|
||||
|
||||
void MediaStreamSignaling::RemoveLocalStream(
|
||||
MediaStreamInterface* local_stream) {
|
||||
local_streams_->RemoveStream(local_stream);
|
||||
AudioTrackVector audio_tracks = local_stream->GetAudioTracks();
|
||||
for (AudioTrackVector::const_iterator it = audio_tracks.begin();
|
||||
it != audio_tracks.end(); ++it) {
|
||||
const TrackInfo* track_info = FindTrackInfo(local_audio_tracks_,
|
||||
local_stream->label(),
|
||||
(*it)->id());
|
||||
if (track_info) {
|
||||
stream_observer_->OnRemoveLocalAudioTrack(local_stream, *it,
|
||||
track_info->ssrc);
|
||||
}
|
||||
}
|
||||
VideoTrackVector video_tracks = local_stream->GetVideoTracks();
|
||||
for (VideoTrackVector::const_iterator it = video_tracks.begin();
|
||||
it != video_tracks.end(); ++it) {
|
||||
const TrackInfo* track_info = FindTrackInfo(local_video_tracks_,
|
||||
local_stream->label(),
|
||||
(*it)->id());
|
||||
if (track_info) {
|
||||
stream_observer_->OnRemoveLocalVideoTrack(local_stream, *it);
|
||||
}
|
||||
}
|
||||
|
||||
local_streams_->RemoveStream(local_stream);
|
||||
stream_observer_->OnRemoveLocalStream(local_stream);
|
||||
}
|
||||
|
||||
@ -725,7 +746,8 @@ void MediaStreamSignaling::UpdateLocalTracks(
|
||||
cricket::StreamParams params;
|
||||
if (!cricket::GetStreamBySsrc(streams, info.ssrc, ¶ms) ||
|
||||
params.id != info.track_id || params.sync_label != info.stream_label) {
|
||||
OnLocalTrackRemoved(info.stream_label, info.track_id, media_type);
|
||||
OnLocalTrackRemoved(info.stream_label, info.track_id, info.ssrc,
|
||||
media_type);
|
||||
track_it = current_tracks->erase(track_it);
|
||||
} else {
|
||||
++track_it;
|
||||
@ -787,6 +809,7 @@ void MediaStreamSignaling::OnLocalTrackSeen(
|
||||
void MediaStreamSignaling::OnLocalTrackRemoved(
|
||||
const std::string& stream_label,
|
||||
const std::string& track_id,
|
||||
uint32 ssrc,
|
||||
cricket::MediaType media_type) {
|
||||
MediaStreamInterface* stream = local_streams_->find(stream_label);
|
||||
if (!stream) {
|
||||
@ -803,7 +826,7 @@ void MediaStreamSignaling::OnLocalTrackRemoved(
|
||||
if (!audio_track) {
|
||||
return;
|
||||
}
|
||||
stream_observer_->OnRemoveLocalAudioTrack(stream, audio_track);
|
||||
stream_observer_->OnRemoveLocalAudioTrack(stream, audio_track, ssrc);
|
||||
} else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
|
||||
VideoTrackInterface* video_track = stream->FindVideoTrack(track_id);
|
||||
if (!video_track) {
|
||||
|
@ -92,7 +92,8 @@ class MediaStreamSignalingObserver {
|
||||
|
||||
// Triggered when the local SessionDescription has removed an audio track.
|
||||
virtual void OnRemoveLocalAudioTrack(MediaStreamInterface* stream,
|
||||
AudioTrackInterface* audio_track) = 0;
|
||||
AudioTrackInterface* audio_track,
|
||||
uint32 ssrc) = 0;
|
||||
|
||||
// Triggered when the local SessionDescription has removed a video track.
|
||||
virtual void OnRemoveLocalVideoTrack(MediaStreamInterface* stream,
|
||||
@ -354,6 +355,7 @@ class MediaStreamSignaling {
|
||||
// MediaStreamTrack in a MediaStream in |local_streams_|.
|
||||
void OnLocalTrackRemoved(const std::string& stream_label,
|
||||
const std::string& track_id,
|
||||
uint32 ssrc,
|
||||
cricket::MediaType media_type);
|
||||
|
||||
void UpdateLocalRtpDataChannels(const cricket::StreamParamsVec& streams);
|
||||
|
@ -298,7 +298,8 @@ class MockSignalingObserver : public webrtc::MediaStreamSignalingObserver {
|
||||
}
|
||||
|
||||
virtual void OnRemoveLocalAudioTrack(MediaStreamInterface* stream,
|
||||
AudioTrackInterface* audio_track) {
|
||||
AudioTrackInterface* audio_track,
|
||||
uint32 ssrc) {
|
||||
RemoveTrack(&local_audio_tracks_, stream, audio_track);
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,10 @@ BEGIN_PROXY_MAP(AudioTrack)
|
||||
PROXY_CONSTMETHOD0(TrackState, state)
|
||||
PROXY_CONSTMETHOD0(bool, enabled)
|
||||
PROXY_CONSTMETHOD0(AudioSourceInterface*, GetSource)
|
||||
PROXY_METHOD1(void, AddSink, AudioTrackSinkInterface*)
|
||||
PROXY_METHOD1(void, RemoveSink, AudioTrackSinkInterface*)
|
||||
PROXY_METHOD1(bool, GetSignalLevel, int*)
|
||||
PROXY_METHOD0(AudioProcessorInterface*, GetAudioProcessor)
|
||||
PROXY_METHOD0(cricket::AudioRenderer*, GetRenderer)
|
||||
|
||||
PROXY_METHOD1(bool, set_enabled, bool)
|
||||
|
@ -706,6 +706,7 @@ void PeerConnection::OnAddLocalAudioTrack(MediaStreamInterface* stream,
|
||||
AudioTrackInterface* audio_track,
|
||||
uint32 ssrc) {
|
||||
stream_handler_container_->AddLocalAudioTrack(stream, audio_track, ssrc);
|
||||
stats_.AddLocalAudioTrack(audio_track, ssrc);
|
||||
}
|
||||
void PeerConnection::OnAddLocalVideoTrack(MediaStreamInterface* stream,
|
||||
VideoTrackInterface* video_track,
|
||||
@ -714,8 +715,10 @@ void PeerConnection::OnAddLocalVideoTrack(MediaStreamInterface* stream,
|
||||
}
|
||||
|
||||
void PeerConnection::OnRemoveLocalAudioTrack(MediaStreamInterface* stream,
|
||||
AudioTrackInterface* audio_track) {
|
||||
AudioTrackInterface* audio_track,
|
||||
uint32 ssrc) {
|
||||
stream_handler_container_->RemoveLocalTrack(stream, audio_track);
|
||||
stats_.RemoveLocalAudioTrack(audio_track, ssrc);
|
||||
}
|
||||
|
||||
void PeerConnection::OnRemoveLocalVideoTrack(MediaStreamInterface* stream,
|
||||
|
@ -136,7 +136,8 @@ class PeerConnection : public PeerConnectionInterface,
|
||||
uint32 ssrc) OVERRIDE;
|
||||
virtual void OnRemoveLocalAudioTrack(
|
||||
MediaStreamInterface* stream,
|
||||
AudioTrackInterface* audio_track) OVERRIDE;
|
||||
AudioTrackInterface* audio_track,
|
||||
uint32 ssrc) OVERRIDE;
|
||||
virtual void OnRemoveLocalVideoTrack(
|
||||
MediaStreamInterface* stream,
|
||||
VideoTrackInterface* video_track) OVERRIDE;
|
||||
|
@ -201,6 +201,19 @@ void StatsReport::AddBoolean(const std::string& name, bool value) {
|
||||
AddValue(name, value ? "true" : "false");
|
||||
}
|
||||
|
||||
void StatsReport::ReplaceValue(const std::string& name,
|
||||
const std::string& value) {
|
||||
for (Values::iterator it = values.begin(); it != values.end(); ++it) {
|
||||
if ((*it).name == name) {
|
||||
it->value = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// It is not reachable here, add an ASSERT to make sure the overwriting is
|
||||
// always a success.
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
namespace {
|
||||
typedef std::map<std::string, StatsReport> StatsMap;
|
||||
|
||||
@ -458,6 +471,32 @@ void StatsCollector::AddStream(MediaStreamInterface* stream) {
|
||||
&reports_);
|
||||
}
|
||||
|
||||
void StatsCollector::AddLocalAudioTrack(AudioTrackInterface* audio_track,
|
||||
uint32 ssrc) {
|
||||
ASSERT(audio_track != NULL);
|
||||
#ifdef _DEBUG
|
||||
for (LocalAudioTrackVector::iterator it = local_audio_tracks_.begin();
|
||||
it != local_audio_tracks_.end(); ++it) {
|
||||
ASSERT(it->first != audio_track || it->second != ssrc);
|
||||
}
|
||||
#endif
|
||||
local_audio_tracks_.push_back(std::make_pair(audio_track, ssrc));
|
||||
}
|
||||
|
||||
void StatsCollector::RemoveLocalAudioTrack(AudioTrackInterface* audio_track,
|
||||
uint32 ssrc) {
|
||||
ASSERT(audio_track != NULL);
|
||||
for (LocalAudioTrackVector::iterator it = local_audio_tracks_.begin();
|
||||
it != local_audio_tracks_.end(); ++it) {
|
||||
if (it->first == audio_track && it->second == ssrc) {
|
||||
local_audio_tracks_.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
bool StatsCollector::GetStats(MediaStreamTrackInterface* track,
|
||||
StatsReports* reports) {
|
||||
ASSERT(reports != NULL);
|
||||
@ -784,6 +823,8 @@ void StatsCollector::ExtractVoiceInfo() {
|
||||
}
|
||||
ExtractStatsFromList(voice_info.receivers, transport_id, this);
|
||||
ExtractStatsFromList(voice_info.senders, transport_id, this);
|
||||
|
||||
UpdateStatsFromExistingLocalAudioTracks();
|
||||
}
|
||||
|
||||
void StatsCollector::ExtractVideoInfo(
|
||||
@ -840,19 +881,86 @@ bool StatsCollector::GetTransportIdFromProxy(const std::string& proxy,
|
||||
return true;
|
||||
}
|
||||
|
||||
StatsReport* StatsCollector::GetOrCreateReport(const std::string& type,
|
||||
const std::string& id) {
|
||||
StatsReport* StatsCollector::GetReport(const std::string& type,
|
||||
const std::string& id) {
|
||||
std::string statsid = StatsId(type, id);
|
||||
StatsReport* report = NULL;
|
||||
std::map<std::string, StatsReport>::iterator it = reports_.find(statsid);
|
||||
if (it == reports_.end()) {
|
||||
report = &reports_[statsid]; // Create new element.
|
||||
report->id = statsid;
|
||||
report->type = type;
|
||||
} else {
|
||||
if (it != reports_.end())
|
||||
report = &(it->second);
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
StatsReport* StatsCollector::GetOrCreateReport(const std::string& type,
|
||||
const std::string& id) {
|
||||
StatsReport* report = GetReport(type, id);
|
||||
if (report == NULL) {
|
||||
std::string statsid = StatsId(type, id);
|
||||
report = &reports_[statsid]; // Create new element.
|
||||
report->id = statsid;
|
||||
report->type = type;
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
void StatsCollector::UpdateStatsFromExistingLocalAudioTracks() {
|
||||
// Loop through the existing local audio tracks.
|
||||
for (LocalAudioTrackVector::const_iterator it = local_audio_tracks_.begin();
|
||||
it != local_audio_tracks_.end(); ++it) {
|
||||
AudioTrackInterface* track = it->first;
|
||||
uint32 ssrc = it->second;
|
||||
std::string ssrc_id = talk_base::ToString<uint32>(ssrc);
|
||||
StatsReport* report = GetReport(StatsReport::kStatsReportTypeSsrc,
|
||||
ssrc_id);
|
||||
ASSERT(report != NULL);
|
||||
|
||||
// The same ssrc can be used by both local and remote audio tracks.
|
||||
std::string track_id;
|
||||
if (!ExtractValueFromReport(*report,
|
||||
StatsReport::kStatsValueNameTrackId,
|
||||
&track_id) ||
|
||||
track_id != track->id()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UpdateReportFromAudioTrack(track, report);
|
||||
}
|
||||
}
|
||||
|
||||
void StatsCollector::UpdateReportFromAudioTrack(AudioTrackInterface* track,
|
||||
StatsReport* report) {
|
||||
ASSERT(track != NULL);
|
||||
if (report == NULL)
|
||||
return;
|
||||
|
||||
int signal_level = 0;
|
||||
if (track->GetSignalLevel(&signal_level)) {
|
||||
report->ReplaceValue(StatsReport::kStatsValueNameAudioInputLevel,
|
||||
talk_base::ToString<int>(signal_level));
|
||||
}
|
||||
|
||||
talk_base::scoped_refptr<AudioProcessorInterface> audio_processor(
|
||||
track->GetAudioProcessor());
|
||||
if (audio_processor.get() == NULL)
|
||||
return;
|
||||
|
||||
AudioProcessorInterface::AudioProcessorStats stats;
|
||||
audio_processor->GetStats(&stats);
|
||||
report->ReplaceValue(StatsReport::kStatsValueNameTypingNoiseState,
|
||||
stats.typing_noise_detected ? "true" : "false");
|
||||
report->ReplaceValue(StatsReport::kStatsValueNameEchoReturnLoss,
|
||||
talk_base::ToString<int>(stats.echo_return_loss));
|
||||
report->ReplaceValue(
|
||||
StatsReport::kStatsValueNameEchoReturnLossEnhancement,
|
||||
talk_base::ToString<int>(stats.echo_return_loss_enhancement));
|
||||
report->ReplaceValue(StatsReport::kStatsValueNameEchoDelayMedian,
|
||||
talk_base::ToString<int>(stats.echo_delay_median_ms));
|
||||
report->ReplaceValue(StatsReport::kStatsValueNameEchoCancellationQualityMin,
|
||||
talk_base::ToString<float>(stats.aec_quality_min));
|
||||
report->ReplaceValue(StatsReport::kStatsValueNameEchoDelayStdDev,
|
||||
talk_base::ToString<int>(stats.echo_delay_std_ms));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -31,8 +31,9 @@
|
||||
#ifndef TALK_APP_WEBRTC_STATSCOLLECTOR_H_
|
||||
#define TALK_APP_WEBRTC_STATSCOLLECTOR_H_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "talk/app/webrtc/mediastreaminterface.h"
|
||||
#include "talk/app/webrtc/peerconnectioninterface.h"
|
||||
@ -57,6 +58,13 @@ class StatsCollector {
|
||||
// to GetStats.
|
||||
void AddStream(MediaStreamInterface* stream);
|
||||
|
||||
// Adds a local audio track that is used for getting some voice statistics.
|
||||
void AddLocalAudioTrack(AudioTrackInterface* audio_track, uint32 ssrc);
|
||||
|
||||
// Removes a local audio tracks that is used for getting some voice
|
||||
// statistics.
|
||||
void RemoveLocalAudioTrack(AudioTrackInterface* audio_track, uint32 ssrc);
|
||||
|
||||
// Gather statistics from the session and store them for future use.
|
||||
void UpdateStats(PeerConnectionInterface::StatsOutputLevel level);
|
||||
|
||||
@ -95,6 +103,13 @@ class StatsCollector {
|
||||
WebRtcSession* session() { return session_; }
|
||||
webrtc::StatsReport* GetOrCreateReport(const std::string& type,
|
||||
const std::string& id);
|
||||
webrtc::StatsReport* GetReport(const std::string& type,
|
||||
const std::string& id);
|
||||
|
||||
// Helper method to get stats from the local audio tracks.
|
||||
void UpdateStatsFromExistingLocalAudioTracks();
|
||||
void UpdateReportFromAudioTrack(AudioTrackInterface* track,
|
||||
StatsReport* report);
|
||||
|
||||
// A map from the report id to the report.
|
||||
std::map<std::string, StatsReport> reports_;
|
||||
@ -103,6 +118,10 @@ class StatsCollector {
|
||||
double stats_gathering_started_;
|
||||
talk_base::Timing timing_;
|
||||
cricket::ProxyTransportMap proxy_to_transport_;
|
||||
|
||||
typedef std::vector<std::pair<AudioTrackInterface*, uint32> >
|
||||
LocalAudioTrackVector;
|
||||
LocalAudioTrackVector local_audio_tracks_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "talk/app/webrtc/statscollector.h"
|
||||
|
||||
#include "talk/app/webrtc/mediastream.h"
|
||||
#include "talk/app/webrtc/mediastreaminterface.h"
|
||||
#include "talk/app/webrtc/mediastreamtrack.h"
|
||||
#include "talk/app/webrtc/videotrack.h"
|
||||
#include "talk/base/base64.h"
|
||||
#include "talk/base/fakesslidentity.h"
|
||||
@ -47,6 +49,8 @@ using testing::Return;
|
||||
using testing::ReturnNull;
|
||||
using testing::SetArgPointee;
|
||||
using webrtc::PeerConnectionInterface;
|
||||
using webrtc::StatsReport;
|
||||
using webrtc::StatsReports;
|
||||
|
||||
namespace cricket {
|
||||
|
||||
@ -63,6 +67,7 @@ const char kNoReports[] = "NO REPORTS";
|
||||
|
||||
// Constant names for track identification.
|
||||
const char kTrackId[] = "somename";
|
||||
const char kAudioTrackId[] = "audio_track_id";
|
||||
const uint32 kSsrcOfTrack = 1234;
|
||||
|
||||
class MockWebRtcSession : public webrtc::WebRtcSession {
|
||||
@ -71,6 +76,7 @@ class MockWebRtcSession : public webrtc::WebRtcSession {
|
||||
: WebRtcSession(channel_manager, talk_base::Thread::Current(),
|
||||
talk_base::Thread::Current(), NULL, NULL) {
|
||||
}
|
||||
MOCK_METHOD0(voice_channel, cricket::VoiceChannel*());
|
||||
MOCK_METHOD0(video_channel, cricket::VideoChannel*());
|
||||
MOCK_METHOD2(GetTrackIdBySsrc, bool(uint32, std::string*));
|
||||
MOCK_METHOD1(GetStats, bool(cricket::SessionStats*));
|
||||
@ -86,10 +92,60 @@ class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel {
|
||||
MOCK_METHOD2(GetStats, bool(const StatsOptions&, cricket::VideoMediaInfo*));
|
||||
};
|
||||
|
||||
bool GetValue(const webrtc::StatsReport* report,
|
||||
class MockVoiceMediaChannel : public cricket::FakeVoiceMediaChannel {
|
||||
public:
|
||||
MockVoiceMediaChannel() : cricket::FakeVoiceMediaChannel(NULL) {
|
||||
}
|
||||
MOCK_METHOD1(GetStats, bool(cricket::VoiceMediaInfo*));
|
||||
};
|
||||
|
||||
class FakeAudioProcessor : public webrtc::AudioProcessorInterface {
|
||||
public:
|
||||
FakeAudioProcessor() {}
|
||||
~FakeAudioProcessor() {}
|
||||
|
||||
private:
|
||||
virtual void GetStats(
|
||||
AudioProcessorInterface::AudioProcessorStats* stats) OVERRIDE {
|
||||
stats->typing_noise_detected = true;
|
||||
stats->echo_return_loss = 2;
|
||||
stats->echo_return_loss_enhancement = 3;
|
||||
stats->echo_delay_median_ms = 4;
|
||||
stats->aec_quality_min = 5.1f;
|
||||
stats->echo_delay_std_ms = 6;
|
||||
}
|
||||
};
|
||||
|
||||
class FakeLocalAudioTrack
|
||||
: public webrtc::MediaStreamTrack<webrtc::AudioTrackInterface> {
|
||||
public:
|
||||
explicit FakeLocalAudioTrack(const std::string& id)
|
||||
: webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(id),
|
||||
processor_(new talk_base::RefCountedObject<FakeAudioProcessor>()) {}
|
||||
std::string kind() const OVERRIDE {
|
||||
return "audio";
|
||||
}
|
||||
virtual webrtc::AudioSourceInterface* GetSource() const OVERRIDE {
|
||||
return NULL;
|
||||
}
|
||||
virtual void AddSink(webrtc::AudioTrackSinkInterface* sink) OVERRIDE {}
|
||||
virtual void RemoveSink(webrtc::AudioTrackSinkInterface* sink) OVERRIDE {}
|
||||
virtual bool GetSignalLevel(int* level) OVERRIDE {
|
||||
*level = 1;
|
||||
return true;
|
||||
}
|
||||
virtual webrtc::AudioProcessorInterface* GetAudioProcessor() OVERRIDE {
|
||||
return processor_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
talk_base::scoped_refptr<FakeAudioProcessor> processor_;
|
||||
};
|
||||
|
||||
bool GetValue(const StatsReport* report,
|
||||
const std::string& name,
|
||||
std::string* value) {
|
||||
webrtc::StatsReport::Values::const_iterator it = report->values.begin();
|
||||
StatsReport::Values::const_iterator it = report->values.begin();
|
||||
for (; it != report->values.end(); ++it) {
|
||||
if (it->name == name) {
|
||||
*value = it->value;
|
||||
@ -100,7 +156,7 @@ bool GetValue(const webrtc::StatsReport* report,
|
||||
}
|
||||
|
||||
std::string ExtractStatsValue(const std::string& type,
|
||||
const webrtc::StatsReports& reports,
|
||||
const StatsReports& reports,
|
||||
const std::string name) {
|
||||
if (reports.empty()) {
|
||||
return kNoReports;
|
||||
@ -119,8 +175,8 @@ std::string ExtractStatsValue(const std::string& type,
|
||||
|
||||
// Finds the |n|-th report of type |type| in |reports|.
|
||||
// |n| starts from 1 for finding the first report.
|
||||
const webrtc::StatsReport* FindNthReportByType(
|
||||
const webrtc::StatsReports& reports, const std::string& type, int n) {
|
||||
const StatsReport* FindNthReportByType(
|
||||
const StatsReports& reports, const std::string& type, int n) {
|
||||
for (size_t i = 0; i < reports.size(); ++i) {
|
||||
if (reports[i].type == type) {
|
||||
n--;
|
||||
@ -131,8 +187,8 @@ const webrtc::StatsReport* FindNthReportByType(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const webrtc::StatsReport* FindReportById(const webrtc::StatsReports& reports,
|
||||
const std::string& id) {
|
||||
const StatsReport* FindReportById(const StatsReports& reports,
|
||||
const std::string& id) {
|
||||
for (size_t i = 0; i < reports.size(); ++i) {
|
||||
if (reports[i].id == id) {
|
||||
return &reports[i];
|
||||
@ -141,16 +197,16 @@ const webrtc::StatsReport* FindReportById(const webrtc::StatsReports& reports,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::string ExtractSsrcStatsValue(webrtc::StatsReports reports,
|
||||
std::string ExtractSsrcStatsValue(StatsReports reports,
|
||||
const std::string& name) {
|
||||
return ExtractStatsValue(
|
||||
webrtc::StatsReport::kStatsReportTypeSsrc, reports, name);
|
||||
StatsReport::kStatsReportTypeSsrc, reports, name);
|
||||
}
|
||||
|
||||
std::string ExtractBweStatsValue(webrtc::StatsReports reports,
|
||||
std::string ExtractBweStatsValue(StatsReports reports,
|
||||
const std::string& name) {
|
||||
return ExtractStatsValue(
|
||||
webrtc::StatsReport::kStatsReportTypeBwe, reports, name);
|
||||
StatsReport::kStatsReportTypeBwe, reports, name);
|
||||
}
|
||||
|
||||
std::string DerToPem(const std::string& der) {
|
||||
@ -167,18 +223,18 @@ std::vector<std::string> DersToPems(
|
||||
return pems;
|
||||
}
|
||||
|
||||
void CheckCertChainReports(const webrtc::StatsReports& reports,
|
||||
void CheckCertChainReports(const StatsReports& reports,
|
||||
const std::vector<std::string>& ders,
|
||||
const std::string& start_id) {
|
||||
std::string certificate_id = start_id;
|
||||
size_t i = 0;
|
||||
while (true) {
|
||||
const webrtc::StatsReport* report = FindReportById(reports, certificate_id);
|
||||
const StatsReport* report = FindReportById(reports, certificate_id);
|
||||
ASSERT_TRUE(report != NULL);
|
||||
|
||||
std::string der_base64;
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, webrtc::StatsReport::kStatsValueNameDer, &der_base64));
|
||||
report, StatsReport::kStatsValueNameDer, &der_base64));
|
||||
std::string der = talk_base::Base64::Decode(der_base64,
|
||||
talk_base::Base64::DO_STRICT);
|
||||
EXPECT_EQ(ders[i], der);
|
||||
@ -186,7 +242,7 @@ void CheckCertChainReports(const webrtc::StatsReports& reports,
|
||||
std::string fingerprint_algorithm;
|
||||
EXPECT_TRUE(GetValue(
|
||||
report,
|
||||
webrtc::StatsReport::kStatsValueNameFingerprintAlgorithm,
|
||||
StatsReport::kStatsValueNameFingerprintAlgorithm,
|
||||
&fingerprint_algorithm));
|
||||
// The digest algorithm for a FakeSSLCertificate is always SHA-1.
|
||||
std::string sha_1_str = talk_base::DIGEST_SHA_1;
|
||||
@ -195,17 +251,68 @@ void CheckCertChainReports(const webrtc::StatsReports& reports,
|
||||
std::string dummy_fingerprint; // Value is not checked.
|
||||
EXPECT_TRUE(GetValue(
|
||||
report,
|
||||
webrtc::StatsReport::kStatsValueNameFingerprint,
|
||||
StatsReport::kStatsValueNameFingerprint,
|
||||
&dummy_fingerprint));
|
||||
|
||||
++i;
|
||||
if (!GetValue(
|
||||
report, webrtc::StatsReport::kStatsValueNameIssuerId, &certificate_id))
|
||||
report, StatsReport::kStatsValueNameIssuerId, &certificate_id))
|
||||
break;
|
||||
}
|
||||
EXPECT_EQ(ders.size(), i);
|
||||
}
|
||||
|
||||
void VerifyVoiceSenderInfoReport(const StatsReport* report,
|
||||
const cricket::VoiceSenderInfo& sinfo) {
|
||||
std::string value_in_report;
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, StatsReport::kStatsValueNameCodecName, &value_in_report));
|
||||
EXPECT_EQ(sinfo.codec_name, value_in_report);
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, StatsReport::kStatsValueNameBytesSent, &value_in_report));
|
||||
EXPECT_EQ(talk_base::ToString<int64>(sinfo.bytes_sent), value_in_report);
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, StatsReport::kStatsValueNamePacketsSent, &value_in_report));
|
||||
EXPECT_EQ(talk_base::ToString<int>(sinfo.packets_sent), value_in_report);
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, StatsReport::kStatsValueNameRtt, &value_in_report));
|
||||
EXPECT_EQ(talk_base::ToString<int>(sinfo.rtt_ms), value_in_report);
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, StatsReport::kStatsValueNameRtt, &value_in_report));
|
||||
EXPECT_EQ(talk_base::ToString<int>(sinfo.rtt_ms), value_in_report);
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, StatsReport::kStatsValueNameJitterReceived, &value_in_report));
|
||||
EXPECT_EQ(talk_base::ToString<int>(sinfo.jitter_ms), value_in_report);
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, StatsReport::kStatsValueNameEchoCancellationQualityMin,
|
||||
&value_in_report));
|
||||
EXPECT_EQ(talk_base::ToString<float>(sinfo.aec_quality_min), value_in_report);
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, StatsReport::kStatsValueNameEchoDelayMedian, &value_in_report));
|
||||
EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_delay_median_ms),
|
||||
value_in_report);
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, StatsReport::kStatsValueNameEchoDelayStdDev, &value_in_report));
|
||||
EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_delay_std_ms),
|
||||
value_in_report);
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, StatsReport::kStatsValueNameEchoReturnLoss, &value_in_report));
|
||||
EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_return_loss),
|
||||
value_in_report);
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, StatsReport::kStatsValueNameEchoReturnLossEnhancement,
|
||||
&value_in_report));
|
||||
EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_return_loss_enhancement),
|
||||
value_in_report);
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, StatsReport::kStatsValueNameAudioInputLevel, &value_in_report));
|
||||
EXPECT_EQ(talk_base::ToString<int>(sinfo.audio_level), value_in_report);
|
||||
EXPECT_TRUE(GetValue(
|
||||
report, StatsReport::kStatsValueNameTypingNoiseState, &value_in_report));
|
||||
std::string typing_detected = sinfo.typing_noise_detected ? "true" : "false";
|
||||
EXPECT_EQ(typing_detected, value_in_report);
|
||||
}
|
||||
|
||||
class StatsCollectorTest : public testing::Test {
|
||||
protected:
|
||||
StatsCollectorTest()
|
||||
@ -245,12 +352,25 @@ class StatsCollectorTest : public testing::Test {
|
||||
Return(true)));
|
||||
}
|
||||
|
||||
// Adds a local audio track with a given SSRC into the stats.
|
||||
void AddLocalAudioTrackStats() {
|
||||
if (stream_ == NULL)
|
||||
stream_ = webrtc::MediaStream::Create("streamlabel");
|
||||
|
||||
audio_track_ =
|
||||
new talk_base::RefCountedObject<FakeLocalAudioTrack>(kAudioTrackId);
|
||||
stream_->AddTrack(audio_track_);
|
||||
EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<1>(kAudioTrackId),
|
||||
Return(true)));
|
||||
}
|
||||
|
||||
void TestCertificateReports(const talk_base::FakeSSLCertificate& local_cert,
|
||||
const std::vector<std::string>& local_ders,
|
||||
const talk_base::FakeSSLCertificate& remote_cert,
|
||||
const std::vector<std::string>& remote_ders) {
|
||||
webrtc::StatsCollector stats; // Implementation under test.
|
||||
webrtc::StatsReports reports; // returned values.
|
||||
StatsReports reports; // returned values.
|
||||
stats.set_session(&session_);
|
||||
|
||||
// Fake stats to process.
|
||||
@ -289,22 +409,22 @@ class StatsCollectorTest : public testing::Test {
|
||||
EXPECT_CALL(session_, GetStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(session_stats),
|
||||
Return(true)));
|
||||
EXPECT_CALL(session_, video_channel())
|
||||
.WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
|
||||
|
||||
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
|
||||
|
||||
stats.GetStats(NULL, &reports);
|
||||
|
||||
const webrtc::StatsReport* channel_report = FindNthReportByType(
|
||||
reports, webrtc::StatsReport::kStatsReportTypeComponent, 1);
|
||||
const StatsReport* channel_report = FindNthReportByType(
|
||||
reports, StatsReport::kStatsReportTypeComponent, 1);
|
||||
EXPECT_TRUE(channel_report != NULL);
|
||||
|
||||
// Check local certificate chain.
|
||||
std::string local_certificate_id = ExtractStatsValue(
|
||||
webrtc::StatsReport::kStatsReportTypeComponent,
|
||||
StatsReport::kStatsReportTypeComponent,
|
||||
reports,
|
||||
webrtc::StatsReport::kStatsValueNameLocalCertificateId);
|
||||
StatsReport::kStatsValueNameLocalCertificateId);
|
||||
if (local_ders.size() > 0) {
|
||||
EXPECT_NE(kNotFound, local_certificate_id);
|
||||
CheckCertChainReports(reports, local_ders, local_certificate_id);
|
||||
@ -314,9 +434,9 @@ class StatsCollectorTest : public testing::Test {
|
||||
|
||||
// Check remote certificate chain.
|
||||
std::string remote_certificate_id = ExtractStatsValue(
|
||||
webrtc::StatsReport::kStatsReportTypeComponent,
|
||||
StatsReport::kStatsReportTypeComponent,
|
||||
reports,
|
||||
webrtc::StatsReport::kStatsValueNameRemoteCertificateId);
|
||||
StatsReport::kStatsValueNameRemoteCertificateId);
|
||||
if (remote_ders.size() > 0) {
|
||||
EXPECT_NE(kNotFound, remote_certificate_id);
|
||||
CheckCertChainReports(reports, remote_ders, remote_certificate_id);
|
||||
@ -331,6 +451,7 @@ class StatsCollectorTest : public testing::Test {
|
||||
cricket::SessionStats session_stats_;
|
||||
talk_base::scoped_refptr<webrtc::MediaStream> stream_;
|
||||
talk_base::scoped_refptr<webrtc::VideoTrack> track_;
|
||||
talk_base::scoped_refptr<FakeLocalAudioTrack> audio_track_;
|
||||
std::string track_id_;
|
||||
};
|
||||
|
||||
@ -340,7 +461,7 @@ TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
|
||||
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
|
||||
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
|
||||
media_engine_, media_channel, &session_, "", false, NULL);
|
||||
webrtc::StatsReports reports; // returned values.
|
||||
StatsReports reports; // returned values.
|
||||
cricket::VideoSenderInfo video_sender_info;
|
||||
cricket::VideoMediaInfo stats_read;
|
||||
// The number of bytes must be larger than 0xFFFFFFFF for this test.
|
||||
@ -356,8 +477,8 @@ TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
|
||||
video_sender_info.bytes_sent = kBytesSent;
|
||||
stats_read.senders.push_back(video_sender_info);
|
||||
|
||||
EXPECT_CALL(session_, video_channel())
|
||||
.WillRepeatedly(Return(&video_channel));
|
||||
EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(*media_channel, GetStats(_, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(stats_read),
|
||||
Return(true)));
|
||||
@ -373,7 +494,7 @@ TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
|
||||
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
|
||||
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
|
||||
media_engine_, media_channel, &session_, "", false, NULL);
|
||||
webrtc::StatsReports reports; // returned values.
|
||||
StatsReports reports; // returned values.
|
||||
cricket::VideoSenderInfo video_sender_info;
|
||||
cricket::VideoMediaInfo stats_read;
|
||||
// Set up an SSRC just to test that we get both kinds of stats back: SSRC and
|
||||
@ -395,8 +516,8 @@ TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
|
||||
bwe.target_enc_bitrate = kTargetEncBitrate;
|
||||
stats_read.bw_estimations.push_back(bwe);
|
||||
|
||||
EXPECT_CALL(session_, video_channel())
|
||||
.WillRepeatedly(Return(&video_channel));
|
||||
EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(*media_channel, GetStats(_, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(stats_read),
|
||||
Return(true)));
|
||||
@ -413,14 +534,14 @@ TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
|
||||
// exists in the returned stats.
|
||||
TEST_F(StatsCollectorTest, SessionObjectExists) {
|
||||
webrtc::StatsCollector stats; // Implementation under test.
|
||||
webrtc::StatsReports reports; // returned values.
|
||||
StatsReports reports; // returned values.
|
||||
stats.set_session(&session_);
|
||||
EXPECT_CALL(session_, video_channel())
|
||||
.WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
|
||||
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
|
||||
stats.GetStats(NULL, &reports);
|
||||
const webrtc::StatsReport* session_report = FindNthReportByType(
|
||||
reports, webrtc::StatsReport::kStatsReportTypeSession, 1);
|
||||
const StatsReport* session_report = FindNthReportByType(
|
||||
reports, StatsReport::kStatsReportTypeSession, 1);
|
||||
EXPECT_FALSE(session_report == NULL);
|
||||
}
|
||||
|
||||
@ -428,18 +549,18 @@ TEST_F(StatsCollectorTest, SessionObjectExists) {
|
||||
// in the returned stats.
|
||||
TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) {
|
||||
webrtc::StatsCollector stats; // Implementation under test.
|
||||
webrtc::StatsReports reports; // returned values.
|
||||
StatsReports reports; // returned values.
|
||||
stats.set_session(&session_);
|
||||
EXPECT_CALL(session_, video_channel())
|
||||
.WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
|
||||
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
|
||||
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
|
||||
stats.GetStats(NULL, &reports);
|
||||
const webrtc::StatsReport* session_report = FindNthReportByType(
|
||||
reports, webrtc::StatsReport::kStatsReportTypeSession, 1);
|
||||
const StatsReport* session_report = FindNthReportByType(
|
||||
reports, StatsReport::kStatsReportTypeSession, 1);
|
||||
EXPECT_FALSE(session_report == NULL);
|
||||
session_report = FindNthReportByType(
|
||||
reports, webrtc::StatsReport::kStatsReportTypeSession, 2);
|
||||
reports, StatsReport::kStatsReportTypeSession, 2);
|
||||
EXPECT_EQ(NULL, session_report);
|
||||
}
|
||||
|
||||
@ -455,18 +576,18 @@ TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) {
|
||||
|
||||
stats.set_session(&session_);
|
||||
|
||||
webrtc::StatsReports reports;
|
||||
StatsReports reports;
|
||||
|
||||
// Verfies the existence of the track report.
|
||||
stats.GetStats(NULL, &reports);
|
||||
EXPECT_EQ((size_t)1, reports.size());
|
||||
EXPECT_EQ(std::string(webrtc::StatsReport::kStatsReportTypeTrack),
|
||||
EXPECT_EQ(std::string(StatsReport::kStatsReportTypeTrack),
|
||||
reports[0].type);
|
||||
|
||||
std::string trackValue =
|
||||
ExtractStatsValue(webrtc::StatsReport::kStatsReportTypeTrack,
|
||||
ExtractStatsValue(StatsReport::kStatsReportTypeTrack,
|
||||
reports,
|
||||
webrtc::StatsReport::kStatsValueNameTrackId);
|
||||
StatsReport::kStatsValueNameTrackId);
|
||||
EXPECT_EQ(kTrackId, trackValue);
|
||||
}
|
||||
|
||||
@ -482,7 +603,7 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
|
||||
|
||||
stats.set_session(&session_);
|
||||
|
||||
webrtc::StatsReports reports;
|
||||
StatsReports reports;
|
||||
|
||||
// Constructs an ssrc stats update.
|
||||
cricket::VideoSenderInfo video_sender_info;
|
||||
@ -494,8 +615,8 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
|
||||
video_sender_info.bytes_sent = kBytesSent;
|
||||
stats_read.senders.push_back(video_sender_info);
|
||||
|
||||
EXPECT_CALL(session_, video_channel())
|
||||
.WillRepeatedly(Return(&video_channel));
|
||||
EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(*media_channel, GetStats(_, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(stats_read),
|
||||
Return(true)));
|
||||
@ -505,8 +626,8 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
|
||||
// |reports| should contain at least one session report, one track report,
|
||||
// and one ssrc report.
|
||||
EXPECT_LE((size_t)3, reports.size());
|
||||
const webrtc::StatsReport* track_report = FindNthReportByType(
|
||||
reports, webrtc::StatsReport::kStatsReportTypeTrack, 1);
|
||||
const StatsReport* track_report = FindNthReportByType(
|
||||
reports, StatsReport::kStatsReportTypeTrack, 1);
|
||||
EXPECT_FALSE(track_report == NULL);
|
||||
|
||||
stats.GetStats(track_, &reports);
|
||||
@ -514,15 +635,15 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
|
||||
// and one ssrc report.
|
||||
EXPECT_LE((size_t)3, reports.size());
|
||||
track_report = FindNthReportByType(
|
||||
reports, webrtc::StatsReport::kStatsReportTypeTrack, 1);
|
||||
reports, StatsReport::kStatsReportTypeTrack, 1);
|
||||
EXPECT_FALSE(track_report == NULL);
|
||||
|
||||
std::string ssrc_id = ExtractSsrcStatsValue(
|
||||
reports, webrtc::StatsReport::kStatsValueNameSsrc);
|
||||
reports, StatsReport::kStatsValueNameSsrc);
|
||||
EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
|
||||
|
||||
std::string track_id = ExtractSsrcStatsValue(
|
||||
reports, webrtc::StatsReport::kStatsValueNameTrackId);
|
||||
reports, StatsReport::kStatsValueNameTrackId);
|
||||
EXPECT_EQ(kTrackId, track_id);
|
||||
}
|
||||
|
||||
@ -540,7 +661,7 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
|
||||
|
||||
stats.set_session(&session_);
|
||||
|
||||
webrtc::StatsReports reports;
|
||||
StatsReports reports;
|
||||
|
||||
// Constructs an ssrc stats update.
|
||||
cricket::VideoSenderInfo video_sender_info;
|
||||
@ -552,26 +673,26 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
|
||||
video_sender_info.bytes_sent = kBytesSent;
|
||||
stats_read.senders.push_back(video_sender_info);
|
||||
|
||||
EXPECT_CALL(session_, video_channel())
|
||||
.WillRepeatedly(Return(&video_channel));
|
||||
EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(*media_channel, GetStats(_, _))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<1>(stats_read),
|
||||
Return(true)));
|
||||
|
||||
InitSessionStats(kVcName);
|
||||
EXPECT_CALL(session_, GetStats(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
|
||||
Return(true)));
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
|
||||
Return(true)));
|
||||
|
||||
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
|
||||
stats.GetStats(NULL, &reports);
|
||||
std::string transport_id = ExtractStatsValue(
|
||||
webrtc::StatsReport::kStatsReportTypeSsrc,
|
||||
StatsReport::kStatsReportTypeSsrc,
|
||||
reports,
|
||||
webrtc::StatsReport::kStatsValueNameTransportId);
|
||||
StatsReport::kStatsValueNameTransportId);
|
||||
ASSERT_NE(kNotFound, transport_id);
|
||||
const webrtc::StatsReport* transport_report = FindReportById(reports,
|
||||
transport_id);
|
||||
const StatsReport* transport_report = FindReportById(reports,
|
||||
transport_id);
|
||||
ASSERT_FALSE(transport_report == NULL);
|
||||
}
|
||||
|
||||
@ -589,14 +710,14 @@ TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) {
|
||||
|
||||
stats.set_session(&session_);
|
||||
|
||||
EXPECT_CALL(session_, video_channel())
|
||||
.WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
|
||||
|
||||
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
|
||||
webrtc::StatsReports reports;
|
||||
StatsReports reports;
|
||||
stats.GetStats(NULL, &reports);
|
||||
const webrtc::StatsReport* remote_report = FindNthReportByType(reports,
|
||||
webrtc::StatsReport::kStatsReportTypeRemoteSsrc, 1);
|
||||
const StatsReport* remote_report = FindNthReportByType(reports,
|
||||
StatsReport::kStatsReportTypeRemoteSsrc, 1);
|
||||
EXPECT_TRUE(remote_report == NULL);
|
||||
}
|
||||
|
||||
@ -614,13 +735,13 @@ TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) {
|
||||
|
||||
stats.set_session(&session_);
|
||||
|
||||
webrtc::StatsReports reports;
|
||||
StatsReports reports;
|
||||
|
||||
// Instruct the session to return stats containing the transport channel.
|
||||
InitSessionStats(kVcName);
|
||||
EXPECT_CALL(session_, GetStats(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
|
||||
Return(true)));
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
|
||||
Return(true)));
|
||||
|
||||
// Constructs an ssrc stats update.
|
||||
cricket::VideoMediaInfo stats_read;
|
||||
@ -633,16 +754,16 @@ TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) {
|
||||
video_sender_info.remote_stats.push_back(remote_ssrc_stats);
|
||||
stats_read.senders.push_back(video_sender_info);
|
||||
|
||||
EXPECT_CALL(session_, video_channel())
|
||||
.WillRepeatedly(Return(&video_channel));
|
||||
EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(*media_channel, GetStats(_, _))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<1>(stats_read),
|
||||
Return(true)));
|
||||
|
||||
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
|
||||
stats.GetStats(NULL, &reports);
|
||||
const webrtc::StatsReport* remote_report = FindNthReportByType(reports,
|
||||
webrtc::StatsReport::kStatsReportTypeRemoteSsrc, 1);
|
||||
const StatsReport* remote_report = FindNthReportByType(reports,
|
||||
StatsReport::kStatsReportTypeRemoteSsrc, 1);
|
||||
EXPECT_FALSE(remote_report == NULL);
|
||||
EXPECT_NE(0, remote_report->timestamp);
|
||||
}
|
||||
@ -689,7 +810,7 @@ TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) {
|
||||
// transport is present.
|
||||
TEST_F(StatsCollectorTest, NoTransport) {
|
||||
webrtc::StatsCollector stats; // Implementation under test.
|
||||
webrtc::StatsReports reports; // returned values.
|
||||
StatsReports reports; // returned values.
|
||||
stats.set_session(&session_);
|
||||
|
||||
// Fake stats to process.
|
||||
@ -711,24 +832,24 @@ TEST_F(StatsCollectorTest, NoTransport) {
|
||||
.WillOnce(DoAll(SetArgPointee<0>(session_stats),
|
||||
Return(true)));
|
||||
|
||||
EXPECT_CALL(session_, video_channel())
|
||||
.WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
|
||||
|
||||
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
|
||||
stats.GetStats(NULL, &reports);
|
||||
|
||||
// Check that the local certificate is absent.
|
||||
std::string local_certificate_id = ExtractStatsValue(
|
||||
webrtc::StatsReport::kStatsReportTypeComponent,
|
||||
StatsReport::kStatsReportTypeComponent,
|
||||
reports,
|
||||
webrtc::StatsReport::kStatsValueNameLocalCertificateId);
|
||||
StatsReport::kStatsValueNameLocalCertificateId);
|
||||
ASSERT_EQ(kNotFound, local_certificate_id);
|
||||
|
||||
// Check that the remote certificate is absent.
|
||||
std::string remote_certificate_id = ExtractStatsValue(
|
||||
webrtc::StatsReport::kStatsReportTypeComponent,
|
||||
StatsReport::kStatsReportTypeComponent,
|
||||
reports,
|
||||
webrtc::StatsReport::kStatsValueNameRemoteCertificateId);
|
||||
StatsReport::kStatsValueNameRemoteCertificateId);
|
||||
ASSERT_EQ(kNotFound, remote_certificate_id);
|
||||
}
|
||||
|
||||
@ -736,7 +857,7 @@ TEST_F(StatsCollectorTest, NoTransport) {
|
||||
// does not have any certificates.
|
||||
TEST_F(StatsCollectorTest, NoCertificates) {
|
||||
webrtc::StatsCollector stats; // Implementation under test.
|
||||
webrtc::StatsReports reports; // returned values.
|
||||
StatsReports reports; // returned values.
|
||||
stats.set_session(&session_);
|
||||
|
||||
// Fake stats to process.
|
||||
@ -764,24 +885,24 @@ TEST_F(StatsCollectorTest, NoCertificates) {
|
||||
EXPECT_CALL(session_, GetStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(session_stats),
|
||||
Return(true)));
|
||||
EXPECT_CALL(session_, video_channel())
|
||||
.WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
|
||||
|
||||
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
|
||||
stats.GetStats(NULL, &reports);
|
||||
|
||||
// Check that the local certificate is absent.
|
||||
std::string local_certificate_id = ExtractStatsValue(
|
||||
webrtc::StatsReport::kStatsReportTypeComponent,
|
||||
StatsReport::kStatsReportTypeComponent,
|
||||
reports,
|
||||
webrtc::StatsReport::kStatsValueNameLocalCertificateId);
|
||||
StatsReport::kStatsValueNameLocalCertificateId);
|
||||
ASSERT_EQ(kNotFound, local_certificate_id);
|
||||
|
||||
// Check that the remote certificate is absent.
|
||||
std::string remote_certificate_id = ExtractStatsValue(
|
||||
webrtc::StatsReport::kStatsReportTypeComponent,
|
||||
StatsReport::kStatsReportTypeComponent,
|
||||
reports,
|
||||
webrtc::StatsReport::kStatsValueNameRemoteCertificateId);
|
||||
StatsReport::kStatsValueNameRemoteCertificateId);
|
||||
ASSERT_EQ(kNotFound, remote_certificate_id);
|
||||
}
|
||||
|
||||
@ -810,7 +931,7 @@ TEST_F(StatsCollectorTest, StatsOutputLevelVerbose) {
|
||||
media_engine_, media_channel, &session_, "", false, NULL);
|
||||
stats.set_session(&session_);
|
||||
|
||||
webrtc::StatsReports reports; // returned values.
|
||||
StatsReports reports; // returned values.
|
||||
cricket::VideoMediaInfo stats_read;
|
||||
cricket::BandwidthEstimationInfo bwe;
|
||||
bwe.total_received_propagation_delta_ms = 10;
|
||||
@ -822,6 +943,7 @@ TEST_F(StatsCollectorTest, StatsOutputLevelVerbose) {
|
||||
|
||||
EXPECT_CALL(session_, video_channel())
|
||||
.WillRepeatedly(Return(&video_channel));
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
|
||||
|
||||
StatsOptions options;
|
||||
options.include_received_propagation_stats = true;
|
||||
@ -844,4 +966,175 @@ TEST_F(StatsCollectorTest, StatsOutputLevelVerbose) {
|
||||
EXPECT_EQ("[1000, 2000]", result);
|
||||
}
|
||||
|
||||
// This test verifies that a local stats object can get statistics via
|
||||
// AudioTrackInterface::GetStats() method.
|
||||
TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) {
|
||||
webrtc::StatsCollector stats; // Implementation under test.
|
||||
MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel();
|
||||
// The content_name known by the voice channel.
|
||||
const std::string kVcName("vcname");
|
||||
cricket::VoiceChannel voice_channel(talk_base::Thread::Current(),
|
||||
media_engine_, media_channel, &session_, kVcName, false);
|
||||
AddLocalAudioTrackStats();
|
||||
stats.AddStream(stream_);
|
||||
stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
|
||||
|
||||
stats.set_session(&session_);
|
||||
|
||||
// Instruct the session to return stats containing the transport channel.
|
||||
InitSessionStats(kVcName);
|
||||
EXPECT_CALL(session_, GetStats(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
|
||||
Return(true)));
|
||||
|
||||
cricket::VoiceSenderInfo voice_sender_info;
|
||||
// Contents won't be modified by the AudioTrackInterface::GetStats().
|
||||
voice_sender_info.add_ssrc(kSsrcOfTrack);
|
||||
voice_sender_info.codec_name = "fake_codec";
|
||||
voice_sender_info.bytes_sent = 100;
|
||||
voice_sender_info.packets_sent = 101;
|
||||
voice_sender_info.rtt_ms = 102;
|
||||
voice_sender_info.fraction_lost = 103;
|
||||
voice_sender_info.jitter_ms = 104;
|
||||
voice_sender_info.packets_lost = 105;
|
||||
voice_sender_info.ext_seqnum = 106;
|
||||
|
||||
// Contents will be modified by the AudioTrackInterface::GetStats().
|
||||
voice_sender_info.audio_level = 107;
|
||||
voice_sender_info.echo_return_loss = 108;;
|
||||
voice_sender_info.echo_return_loss_enhancement = 109;
|
||||
voice_sender_info.echo_delay_median_ms = 110;
|
||||
voice_sender_info.echo_delay_std_ms = 111;
|
||||
voice_sender_info.aec_quality_min = 112.0f;
|
||||
voice_sender_info.typing_noise_detected = false;
|
||||
|
||||
// Constructs an ssrc stats update.
|
||||
cricket::VoiceMediaInfo stats_read;
|
||||
stats_read.senders.push_back(voice_sender_info);
|
||||
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel));
|
||||
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(*media_channel, GetStats(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(stats_read),
|
||||
Return(true)));
|
||||
|
||||
StatsReports reports; // returned values.
|
||||
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
|
||||
stats.GetStats(NULL, &reports);
|
||||
|
||||
// Verfy the existence of the track report.
|
||||
const StatsReport* report = FindNthReportByType(
|
||||
reports, StatsReport::kStatsReportTypeSsrc, 1);
|
||||
EXPECT_FALSE(report == NULL);
|
||||
std::string track_id = ExtractSsrcStatsValue(
|
||||
reports, StatsReport::kStatsValueNameTrackId);
|
||||
EXPECT_EQ(kAudioTrackId, track_id);
|
||||
std::string ssrc_id = ExtractSsrcStatsValue(
|
||||
reports, StatsReport::kStatsValueNameSsrc);
|
||||
EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
|
||||
|
||||
// Verifies the values in the track report.
|
||||
audio_track_->GetSignalLevel(&voice_sender_info.audio_level);
|
||||
webrtc::AudioProcessorInterface::AudioProcessorStats audio_processor_stats;
|
||||
audio_track_->GetAudioProcessor()->GetStats(&audio_processor_stats);
|
||||
voice_sender_info.typing_noise_detected =
|
||||
audio_processor_stats.typing_noise_detected;
|
||||
voice_sender_info.echo_return_loss = audio_processor_stats.echo_return_loss;
|
||||
voice_sender_info.echo_return_loss_enhancement =
|
||||
audio_processor_stats.echo_return_loss_enhancement;
|
||||
voice_sender_info.echo_delay_median_ms =
|
||||
audio_processor_stats.echo_delay_median_ms;
|
||||
voice_sender_info.aec_quality_min = audio_processor_stats.aec_quality_min;
|
||||
voice_sender_info.echo_delay_std_ms = audio_processor_stats.echo_delay_std_ms;
|
||||
VerifyVoiceSenderInfoReport(report, voice_sender_info);
|
||||
|
||||
// Verify we get the same result by passing a track to GetStats().
|
||||
StatsReports track_reports; // returned values.
|
||||
stats.GetStats(audio_track_.get(), &track_reports);
|
||||
const StatsReport* track_report = FindNthReportByType(
|
||||
track_reports, StatsReport::kStatsReportTypeSsrc, 1);
|
||||
EXPECT_FALSE(track_report == NULL);
|
||||
track_id = ExtractSsrcStatsValue(track_reports,
|
||||
StatsReport::kStatsValueNameTrackId);
|
||||
EXPECT_EQ(kAudioTrackId, track_id);
|
||||
ssrc_id = ExtractSsrcStatsValue(track_reports,
|
||||
StatsReport::kStatsValueNameSsrc);
|
||||
EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
|
||||
VerifyVoiceSenderInfoReport(track_report, voice_sender_info);
|
||||
}
|
||||
|
||||
// This test verifies that a local stats object won't update its statistics
|
||||
// after a RemoveLocalAudioTrack() call.
|
||||
TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) {
|
||||
webrtc::StatsCollector stats; // Implementation under test.
|
||||
MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel();
|
||||
// The content_name known by the voice channel.
|
||||
const std::string kVcName("vcname");
|
||||
cricket::VoiceChannel voice_channel(talk_base::Thread::Current(),
|
||||
media_engine_, media_channel, &session_, kVcName, false);
|
||||
AddLocalAudioTrackStats();
|
||||
stats.AddStream(stream_);
|
||||
stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
|
||||
|
||||
stats.set_session(&session_);
|
||||
|
||||
// Instruct the session to return stats containing the transport channel.
|
||||
InitSessionStats(kVcName);
|
||||
EXPECT_CALL(session_, GetStats(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
|
||||
Return(true)));
|
||||
|
||||
stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
|
||||
cricket::VoiceSenderInfo voice_sender_info;
|
||||
// Contents won't be modified by the AudioTrackInterface::GetStats().
|
||||
voice_sender_info.add_ssrc(kSsrcOfTrack);
|
||||
voice_sender_info.codec_name = "fake_codec";
|
||||
voice_sender_info.bytes_sent = 100;
|
||||
voice_sender_info.packets_sent = 101;
|
||||
voice_sender_info.rtt_ms = 102;
|
||||
voice_sender_info.fraction_lost = 103;
|
||||
voice_sender_info.jitter_ms = 104;
|
||||
voice_sender_info.packets_lost = 105;
|
||||
voice_sender_info.ext_seqnum = 106;
|
||||
|
||||
// Contents will be modified by the AudioTrackInterface::GetStats().
|
||||
voice_sender_info.audio_level = 107;
|
||||
voice_sender_info.echo_return_loss = 108;;
|
||||
voice_sender_info.echo_return_loss_enhancement = 109;
|
||||
voice_sender_info.echo_delay_median_ms = 110;
|
||||
voice_sender_info.echo_delay_std_ms = 111;
|
||||
voice_sender_info.aec_quality_min = 112;
|
||||
voice_sender_info.typing_noise_detected = false;
|
||||
|
||||
// Constructs an ssrc stats update.
|
||||
cricket::VoiceMediaInfo stats_read;
|
||||
stats_read.senders.push_back(voice_sender_info);
|
||||
|
||||
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel));
|
||||
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(*media_channel, GetStats(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(stats_read),
|
||||
Return(true)));
|
||||
|
||||
StatsReports reports; // returned values.
|
||||
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
|
||||
stats.GetStats(NULL, &reports);
|
||||
|
||||
// The report will exist since we don't remove them in RemoveStream().
|
||||
const StatsReport* report = FindNthReportByType(
|
||||
reports, StatsReport::kStatsReportTypeSsrc, 1);
|
||||
EXPECT_FALSE(report == NULL);
|
||||
std::string track_id = ExtractSsrcStatsValue(
|
||||
reports, StatsReport::kStatsValueNameTrackId);
|
||||
EXPECT_EQ(kAudioTrackId, track_id);
|
||||
std::string ssrc_id = ExtractSsrcStatsValue(
|
||||
reports, StatsReport::kStatsValueNameSsrc);
|
||||
EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
|
||||
|
||||
// Verifies the values in the track report, no value will be changed by the
|
||||
// AudioTrackInterface::GetSignalValue() and
|
||||
// AudioProcessorInterface::AudioProcessorStats::GetStats();
|
||||
VerifyVoiceSenderInfoReport(report, voice_sender_info);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -57,6 +57,8 @@ class StatsReport {
|
||||
void AddValue(const std::string& name, const std::vector<T>& value);
|
||||
void AddBoolean(const std::string& name, bool value);
|
||||
|
||||
void ReplaceValue(const std::string& name, const std::string& value);
|
||||
|
||||
double timestamp; // Time since 1970-01-01T00:00:00Z in milliseconds.
|
||||
typedef std::vector<Value> Values;
|
||||
Values values;
|
||||
|
@ -122,7 +122,8 @@ class FakeMediaStreamSignaling : public webrtc::MediaStreamSignaling,
|
||||
|
||||
virtual void OnRemoveLocalAudioTrack(
|
||||
webrtc::MediaStreamInterface* stream,
|
||||
webrtc::AudioTrackInterface* audio_track) {
|
||||
webrtc::AudioTrackInterface* audio_track,
|
||||
uint32 ssrc) {
|
||||
}
|
||||
virtual void OnRemoveLocalVideoTrack(
|
||||
webrtc::MediaStreamInterface* stream,
|
||||
|
@ -45,9 +45,6 @@
|
||||
#include "talk/examples/call/console.h"
|
||||
#include "talk/examples/call/mediaenginefactory.h"
|
||||
#include "talk/p2p/base/constants.h"
|
||||
#ifdef ANDROID
|
||||
#include "talk/media/other/androidmediaengine.h"
|
||||
#endif
|
||||
#include "talk/session/media/mediasessionclient.h"
|
||||
#include "talk/session/media/srtpfilter.h"
|
||||
#include "talk/xmpp/xmppauth.h"
|
||||
@ -185,7 +182,7 @@ static const int DEFAULT_PORT = 5222;
|
||||
static std::vector<cricket::AudioCodec> codecs;
|
||||
static const cricket::AudioCodec ISAC(103, "ISAC", 40000, 16000, 1, 0);
|
||||
|
||||
cricket::MediaEngine *AndroidMediaEngineFactory() {
|
||||
cricket::MediaEngineInterface *CreateAndroidMediaEngine() {
|
||||
cricket::FakeMediaEngine *engine = new cricket::FakeMediaEngine();
|
||||
|
||||
codecs.push_back(ISAC);
|
||||
@ -438,7 +435,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
InitAndroidMediaEngineFactory(AndroidMediaEngineFactory);
|
||||
MediaEngineFactory::SetCreateFunction(&CreateAndroidMediaEngine);
|
||||
#endif
|
||||
|
||||
#if WIN32
|
||||
|
@ -42,6 +42,13 @@ const int MediaEngineInterface::kDefaultAudioDelayOffset = 0;
|
||||
#if defined(HAVE_WEBRTC_VIDEO)
|
||||
#include "talk/media/webrtc/webrtcvideoengine.h"
|
||||
#endif // HAVE_WEBRTC_VIDEO
|
||||
#if defined(HAVE_LMI)
|
||||
#include "talk/media/base/hybridvideoengine.h"
|
||||
#include "talk/media/lmi/lmimediaengine.h"
|
||||
#endif // HAVE_LMI
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif // HAVE_CONFIG
|
||||
|
||||
namespace cricket {
|
||||
#if defined(HAVE_WEBRTC_VOICE)
|
||||
@ -51,22 +58,59 @@ namespace cricket {
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_WEBRTC_VIDEO)
|
||||
#if !defined(HAVE_LMI)
|
||||
template<>
|
||||
CompositeMediaEngine<WebRtcVoiceEngine, WebRtcVideoEngine>::
|
||||
CompositeMediaEngine() {
|
||||
video_.SetVoiceEngine(&voice_);
|
||||
}
|
||||
#define VIDEO_ENG_NAME WebRtcVideoEngine
|
||||
#else
|
||||
// If we have both WebRtcVideoEngine and LmiVideoEngine, enable dual-stack.
|
||||
// This small class here allows us to hook the WebRtcVideoChannel up to
|
||||
// the capturer owned by the LMI engine, without infecting the rest of the
|
||||
// HybridVideoEngine classes with this abstraction violation.
|
||||
class WebRtcLmiHybridVideoEngine
|
||||
: public HybridVideoEngine<WebRtcVideoEngine, LmiVideoEngine> {
|
||||
public:
|
||||
void SetVoiceEngine(WebRtcVoiceEngine* engine) {
|
||||
video1_.SetVoiceEngine(engine);
|
||||
}
|
||||
};
|
||||
template<>
|
||||
CompositeMediaEngine<WebRtcVoiceEngine, WebRtcLmiHybridVideoEngine>::
|
||||
CompositeMediaEngine() {
|
||||
video_.SetVoiceEngine(&voice_);
|
||||
}
|
||||
#define VIDEO_ENG_NAME WebRtcLmiHybridVideoEngine
|
||||
#endif
|
||||
#elif defined(HAVE_LMI)
|
||||
#define VIDEO_ENG_NAME LmiVideoEngine
|
||||
#else
|
||||
#define VIDEO_ENG_NAME NullVideoEngine
|
||||
#endif
|
||||
|
||||
MediaEngineFactory::MediaEngineCreateFunction
|
||||
MediaEngineFactory::create_function_ = NULL;
|
||||
MediaEngineFactory::MediaEngineCreateFunction
|
||||
MediaEngineFactory::SetCreateFunction(MediaEngineCreateFunction function) {
|
||||
MediaEngineCreateFunction old_function = create_function_;
|
||||
create_function_ = function;
|
||||
return old_function;
|
||||
};
|
||||
|
||||
MediaEngineInterface* MediaEngineFactory::Create() {
|
||||
if (create_function_) {
|
||||
return create_function_();
|
||||
} else {
|
||||
#if defined(HAVE_LINPHONE)
|
||||
return new LinphoneMediaEngine("", "");
|
||||
return new LinphoneMediaEngine("", "");
|
||||
#elif defined(AUDIO_ENG_NAME) && defined(VIDEO_ENG_NAME)
|
||||
return new CompositeMediaEngine<AUDIO_ENG_NAME, VIDEO_ENG_NAME>();
|
||||
return new CompositeMediaEngine<AUDIO_ENG_NAME, VIDEO_ENG_NAME>();
|
||||
#else
|
||||
return new NullMediaEngine();
|
||||
return new NullMediaEngine();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace cricket
|
||||
|
@ -157,7 +157,18 @@ class MediaEngineInterface {
|
||||
#if !defined(DISABLE_MEDIA_ENGINE_FACTORY)
|
||||
class MediaEngineFactory {
|
||||
public:
|
||||
typedef cricket::MediaEngineInterface* (*MediaEngineCreateFunction)();
|
||||
// Creates a media engine, using either the compiled system default or the
|
||||
// creation function specified in SetCreateFunction, if specified.
|
||||
static MediaEngineInterface* Create();
|
||||
// Sets the function used when calling Create. If unset, the compiled system
|
||||
// default will be used. Returns the old create function, or NULL if one
|
||||
// wasn't set. Likewise, NULL can be used as the |function| parameter to
|
||||
// reset to the default behavior.
|
||||
static MediaEngineCreateFunction SetCreateFunction(
|
||||
MediaEngineCreateFunction function);
|
||||
private:
|
||||
static MediaEngineCreateFunction create_function_;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
0
talk/media/other/androidmediaengine.cc
Normal file
0
talk/media/other/androidmediaengine.cc
Normal file
0
talk/media/other/androidmediaengine.h
Normal file
0
talk/media/other/androidmediaengine.h
Normal file
Loading…
x
Reference in New Issue
Block a user