Revert "Encode log events periodically instead of for every event."
This reverts commit b154c27e72fddb6c0d7cac69a9c68fff22154519. Reason for revert: Broke the internal project. Original change's description: > Encode log events periodically instead of for every event. > > Updated unit test to take output_period and random seed as parameters. > Updated the peerconnection interface to allow passing in an output_period. > > This is in preparation of some upcoming CLs that will change the format > to store batches of delta-encoded values. > > > Bug: webrtc:8111 > Change-Id: Id5d9844dfad8d8edad346cd7cbebc7eadaaa5416 > Reviewed-on: https://webrtc-review.googlesource.com/22600 > Commit-Queue: Björn Terelius <terelius@webrtc.org> > Reviewed-by: Elad Alon <eladalon@webrtc.org> > Reviewed-by: Tommi <tommi@webrtc.org> > Reviewed-by: Erik Språng <sprang@webrtc.org> > Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org> > Cr-Commit-Position: refs/heads/master@{#20736} TBR=solenberg@webrtc.org,eladalon@webrtc.org,terelius@webrtc.org,tommi@webrtc.org,sprang@webrtc.org,pthatcher@webrtc.org Change-Id: I2257c46c014adb8c7c4fb28538635cabed1f2229 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: webrtc:8111 Reviewed-on: https://webrtc-review.googlesource.com/24160 Reviewed-by: Zhi Huang <zhihuang@webrtc.org> Commit-Queue: Zhi Huang <zhihuang@webrtc.org> Cr-Commit-Position: refs/heads/master@{#20738}
This commit is contained in:
@ -828,19 +828,10 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
|
||||
// Start RtcEventLog using an existing output-sink. Takes ownership of
|
||||
// |output| and passes it on to Call, which will take the ownership. If the
|
||||
// operation fails the output will be closed and deallocated.
|
||||
// TODO(eladalon): Deprecate and remove this.
|
||||
virtual bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start RtcEventLog using an existing output-sink. Takes ownership of
|
||||
// |output| and passes it on to Call, which will take the ownership. If the
|
||||
// operation fails the output will be closed and deallocated.
|
||||
virtual bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output,
|
||||
int64_t output_period_ms) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stops logging the RtcEventLog.
|
||||
// TODO(ivoc): Make this pure virtual when Chrome is updated.
|
||||
virtual void StopRtcEventLog() {}
|
||||
|
||||
@ -20,11 +20,10 @@ namespace webrtc {
|
||||
|
||||
class MockRtcEventLog : public RtcEventLog {
|
||||
public:
|
||||
virtual bool StartLogging(std::unique_ptr<RtcEventLogOutput> output,
|
||||
int64_t output_period_ms) {
|
||||
return StartLoggingProxy(output.get(), output_period_ms);
|
||||
virtual bool StartLogging(std::unique_ptr<RtcEventLogOutput> output) {
|
||||
return StartLoggingProxy(output.get());
|
||||
}
|
||||
MOCK_METHOD2(StartLoggingProxy, bool(RtcEventLogOutput*, int64_t));
|
||||
MOCK_METHOD1(StartLoggingProxy, bool(RtcEventLogOutput*));
|
||||
|
||||
MOCK_METHOD0(StopLogging, void());
|
||||
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/ptr_util.h"
|
||||
#include "rtc_base/safe_conversions.h"
|
||||
#include "rtc_base/safe_minmax.h"
|
||||
#include "rtc_base/sequenced_task_checker.h"
|
||||
#include "rtc_base/task_queue.h"
|
||||
#include "rtc_base/thread_annotations.h"
|
||||
@ -88,8 +87,7 @@ class RtcEventLogImpl final : public RtcEventLog {
|
||||
|
||||
// TODO(eladalon): We should change these name to reflect that what we're
|
||||
// actually starting/stopping is the output of the log, not the log itself.
|
||||
bool StartLogging(std::unique_ptr<RtcEventLogOutput> output,
|
||||
int64_t output_period_ms) override;
|
||||
bool StartLogging(std::unique_ptr<RtcEventLogOutput> output) override;
|
||||
void StopLogging() override;
|
||||
|
||||
void Log(std::unique_ptr<RtcEvent> event) override;
|
||||
@ -115,8 +113,6 @@ class RtcEventLogImpl final : public RtcEventLog {
|
||||
|
||||
void StopLoggingInternal() RTC_RUN_ON(&task_queue_);
|
||||
|
||||
void ScheduleOutput() RTC_RUN_ON(&task_queue_);
|
||||
|
||||
// Make sure that the event log is "managed" - created/destroyed, as well
|
||||
// as started/stopped - from the same thread/task-queue.
|
||||
rtc::SequencedTaskChecker owner_sequence_checker_;
|
||||
@ -134,15 +130,8 @@ class RtcEventLogImpl final : public RtcEventLog {
|
||||
std::unique_ptr<RtcEventLogEncoder> event_encoder_ RTC_ACCESS_ON(task_queue_);
|
||||
std::unique_ptr<RtcEventLogOutput> event_output_ RTC_ACCESS_ON(task_queue_);
|
||||
|
||||
size_t num_config_events_written_ RTC_ACCESS_ON(task_queue_);
|
||||
int64_t output_period_ms_ RTC_ACCESS_ON(task_queue_);
|
||||
int64_t last_output_ms_ RTC_ACCESS_ON(task_queue_);
|
||||
bool output_scheduled_ RTC_ACCESS_ON(task_queue_);
|
||||
|
||||
// Since we are posting tasks bound to |this|, it is critical that the event
|
||||
// log and it's members outlive the |task_queue_|. Keep the "task_queue_|
|
||||
// last to ensure it destructs first, or else tasks living on the queue might
|
||||
// access other members after they've been torn down.
|
||||
// Keep this last to ensure it destructs first, or else tasks living on the
|
||||
// queue might access other members after they've been torn down.
|
||||
rtc::TaskQueue task_queue_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(RtcEventLogImpl);
|
||||
@ -153,10 +142,6 @@ RtcEventLogImpl::RtcEventLogImpl(
|
||||
: max_size_bytes_(std::numeric_limits<decltype(max_size_bytes_)>::max()),
|
||||
written_bytes_(0),
|
||||
event_encoder_(std::move(event_encoder)),
|
||||
num_config_events_written_(0),
|
||||
output_period_ms_(kImmediateOutput),
|
||||
last_output_ms_(rtc::TimeMillis()),
|
||||
output_scheduled_(false),
|
||||
task_queue_("rtc_event_log") {}
|
||||
|
||||
RtcEventLogImpl::~RtcEventLogImpl() {
|
||||
@ -169,15 +154,10 @@ RtcEventLogImpl::~RtcEventLogImpl() {
|
||||
RTC_DCHECK_GE(count, 0);
|
||||
}
|
||||
|
||||
bool RtcEventLogImpl::StartLogging(std::unique_ptr<RtcEventLogOutput> output,
|
||||
int64_t output_period_ms) {
|
||||
bool RtcEventLogImpl::StartLogging(std::unique_ptr<RtcEventLogOutput> output) {
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&owner_sequence_checker_);
|
||||
|
||||
RTC_DCHECK(output_period_ms == kImmediateOutput || output_period_ms > 0);
|
||||
|
||||
if (!output->IsActive()) {
|
||||
// TODO(eladalon): We may want to remove the IsActive method. Otherwise
|
||||
// we probably want to be consistent and terminate any existing output.
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -190,12 +170,10 @@ bool RtcEventLogImpl::StartLogging(std::unique_ptr<RtcEventLogOutput> output,
|
||||
// to comply with LogToOutput()'s signature - but it's a small problem.
|
||||
RtcEventLoggingStarted start_event;
|
||||
|
||||
// Binding to |this| is safe because |this| outlives the |task_queue_|.
|
||||
auto start = [this, start_event](std::unique_ptr<RtcEventLogOutput> output) {
|
||||
RTC_DCHECK_RUN_ON(&task_queue_);
|
||||
RTC_DCHECK(output->IsActive());
|
||||
event_output_ = std::move(output);
|
||||
num_config_events_written_ = 0;
|
||||
LogToOutput(rtc::MakeUnique<RtcEventLoggingStarted>(start_event));
|
||||
LogEventsFromMemoryToOutput();
|
||||
};
|
||||
@ -213,13 +191,8 @@ void RtcEventLogImpl::StopLogging() {
|
||||
|
||||
rtc::Event output_stopped(true, false);
|
||||
|
||||
// Binding to |this| is safe because |this| outlives the |task_queue_|.
|
||||
task_queue_.PostTask([this, &output_stopped]() {
|
||||
RTC_DCHECK_RUN_ON(&task_queue_);
|
||||
if (event_output_) {
|
||||
RTC_DCHECK(event_output_->IsActive());
|
||||
LogEventsFromMemoryToOutput();
|
||||
}
|
||||
StopLoggingInternal();
|
||||
output_stopped.Set();
|
||||
});
|
||||
@ -232,53 +205,19 @@ void RtcEventLogImpl::StopLogging() {
|
||||
void RtcEventLogImpl::Log(std::unique_ptr<RtcEvent> event) {
|
||||
RTC_DCHECK(event);
|
||||
|
||||
// Binding to |this| is safe because |this| outlives the |task_queue_|.
|
||||
auto event_handler = [this](std::unique_ptr<RtcEvent> unencoded_event) {
|
||||
RTC_DCHECK_RUN_ON(&task_queue_);
|
||||
LogToMemory(std::move(unencoded_event));
|
||||
if (event_output_)
|
||||
ScheduleOutput();
|
||||
if (event_output_) {
|
||||
LogToOutput(std::move(unencoded_event));
|
||||
} else {
|
||||
LogToMemory(std::move(unencoded_event));
|
||||
}
|
||||
};
|
||||
|
||||
task_queue_.PostTask(rtc::MakeUnique<ResourceOwningTask<RtcEvent>>(
|
||||
std::move(event), event_handler));
|
||||
}
|
||||
|
||||
void RtcEventLogImpl::ScheduleOutput() {
|
||||
RTC_DCHECK(event_output_ && event_output_->IsActive());
|
||||
if (history_.size() >= kMaxEventsInHistory) {
|
||||
// We have to emergency drain the buffer. We can't wait for the scheduled
|
||||
// output task because there might be other event incoming before that.
|
||||
LogEventsFromMemoryToOutput();
|
||||
return;
|
||||
}
|
||||
|
||||
if (output_period_ms_ == kImmediateOutput) {
|
||||
// We are already on the |task_queue_| so there is no reason to post a task
|
||||
// if we want to output immediately.
|
||||
LogEventsFromMemoryToOutput();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!output_scheduled_) {
|
||||
output_scheduled_ = true;
|
||||
// Binding to |this| is safe because |this| outlives the |task_queue_|.
|
||||
auto output_task = [this]() {
|
||||
RTC_DCHECK_RUN_ON(&task_queue_);
|
||||
if (event_output_) {
|
||||
RTC_DCHECK(event_output_->IsActive());
|
||||
LogEventsFromMemoryToOutput();
|
||||
}
|
||||
output_scheduled_ = false;
|
||||
};
|
||||
int64_t now_ms = rtc::TimeMillis();
|
||||
int64_t time_since_output_ms = now_ms - last_output_ms_;
|
||||
uint32_t delay = rtc::SafeClamp(output_period_ms_ - time_since_output_ms, 0,
|
||||
output_period_ms_);
|
||||
task_queue_.PostDelayedTask(output_task, delay);
|
||||
}
|
||||
}
|
||||
|
||||
bool RtcEventLogImpl::AppendEventToString(const RtcEvent& event,
|
||||
std::string* output_string) {
|
||||
RTC_DCHECK_RUN_ON(&task_queue_);
|
||||
@ -300,13 +239,14 @@ bool RtcEventLogImpl::AppendEventToString(const RtcEvent& event,
|
||||
}
|
||||
|
||||
void RtcEventLogImpl::LogToMemory(std::unique_ptr<RtcEvent> event) {
|
||||
RTC_DCHECK(!event_output_);
|
||||
|
||||
std::deque<std::unique_ptr<RtcEvent>>& container =
|
||||
event->IsConfigEvent() ? config_history_ : history_;
|
||||
const size_t container_max_size =
|
||||
event->IsConfigEvent() ? kMaxEventsInConfigHistory : kMaxEventsInHistory;
|
||||
|
||||
if (container.size() >= container_max_size) {
|
||||
RTC_DCHECK(!event_output_); // Shouldn't lose events if we have an output.
|
||||
container.pop_front();
|
||||
}
|
||||
container.push_back(std::move(event));
|
||||
@ -314,21 +254,17 @@ void RtcEventLogImpl::LogToMemory(std::unique_ptr<RtcEvent> event) {
|
||||
|
||||
void RtcEventLogImpl::LogEventsFromMemoryToOutput() {
|
||||
RTC_DCHECK(event_output_ && event_output_->IsActive());
|
||||
last_output_ms_ = rtc::TimeMillis();
|
||||
|
||||
std::string output_string;
|
||||
|
||||
// Serialize all stream configurations that haven't already been written to
|
||||
// this output. |num_config_events_written_| is used to track which configs we
|
||||
// have already written. (Note that the config may have been written to
|
||||
// previous outputs; configs are not discarded.)
|
||||
// Serialize the config information for all old streams, including streams
|
||||
// which were already logged to previous outputs.
|
||||
bool appended = true;
|
||||
while (num_config_events_written_ < config_history_.size()) {
|
||||
appended = AppendEventToString(*config_history_[num_config_events_written_],
|
||||
&output_string);
|
||||
if (!appended)
|
||||
for (auto& event : config_history_) {
|
||||
if (!AppendEventToString(*event, &output_string)) {
|
||||
appended = false;
|
||||
break;
|
||||
++num_config_events_written_;
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize the events in the event queue.
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "api/rtceventlogoutput.h"
|
||||
#include "logging/rtc_event_log/events/rtc_event.h"
|
||||
@ -27,7 +26,6 @@ enum PacketDirection { kIncomingPacket = 0, kOutgoingPacket };
|
||||
class RtcEventLog {
|
||||
public:
|
||||
enum : size_t { kUnlimitedOutput = 0 };
|
||||
enum : int64_t { kImmediateOutput = 0 };
|
||||
|
||||
// TODO(eladalon): Two stages are upcoming.
|
||||
// 1. Extend this to actually support the new encoding.
|
||||
@ -51,8 +49,7 @@ class RtcEventLog {
|
||||
|
||||
// Starts logging to a given output. The output might be limited in size,
|
||||
// and may close itself once it has reached the maximum size.
|
||||
virtual bool StartLogging(std::unique_ptr<RtcEventLogOutput> output,
|
||||
int64_t output_period_ms) = 0;
|
||||
virtual bool StartLogging(std::unique_ptr<RtcEventLogOutput> output) = 0;
|
||||
|
||||
// Stops logging to file and waits until the file has been closed, after
|
||||
// which it would be permissible to read and/or modify it.
|
||||
@ -65,8 +62,7 @@ class RtcEventLog {
|
||||
// No-op implementation is used if flag is not set, or in tests.
|
||||
class RtcEventLogNullImpl : public RtcEventLog {
|
||||
public:
|
||||
bool StartLogging(std::unique_ptr<RtcEventLogOutput> output,
|
||||
int64_t output_period_ms) override {
|
||||
bool StartLogging(std::unique_ptr<RtcEventLogOutput> output) override {
|
||||
return false;
|
||||
}
|
||||
void StopLogging() override {}
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@ -300,12 +299,10 @@ void GenerateAudioNetworkAdaptation(const RtpHeaderExtensionMap& extensions,
|
||||
rtc::Optional<float>(prng->Rand<float>());
|
||||
}
|
||||
|
||||
class RtcEventLogSession
|
||||
: public ::testing::TestWithParam<std::tuple<uint64_t, int64_t>> {
|
||||
class RtcEventLogSessionDescription {
|
||||
public:
|
||||
RtcEventLogSession()
|
||||
: prng(std::get<0>(GetParam())),
|
||||
output_period_ms(std::get<1>(GetParam())) {}
|
||||
explicit RtcEventLogSessionDescription(unsigned int random_seed)
|
||||
: prng(random_seed) {}
|
||||
void GenerateSessionDescription(size_t incoming_rtp_count,
|
||||
size_t outgoing_rtp_count,
|
||||
size_t incoming_rtcp_count,
|
||||
@ -331,10 +328,9 @@ class RtcEventLogSession
|
||||
std::vector<rtclog::StreamConfig> sender_configs;
|
||||
std::vector<EventType> event_types;
|
||||
Random prng;
|
||||
int64_t output_period_ms;
|
||||
};
|
||||
|
||||
void RtcEventLogSession::GenerateSessionDescription(
|
||||
void RtcEventLogSessionDescription::GenerateSessionDescription(
|
||||
size_t incoming_rtp_count,
|
||||
size_t outgoing_rtp_count,
|
||||
size_t incoming_rtcp_count,
|
||||
@ -407,14 +403,12 @@ void RtcEventLogSession::GenerateSessionDescription(
|
||||
}
|
||||
}
|
||||
|
||||
void RtcEventLogSession::WriteSession() {
|
||||
void RtcEventLogSessionDescription::WriteSession() {
|
||||
// Find the name of the current test, in order to use it as a temporary
|
||||
// filename.
|
||||
auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
|
||||
std::string test_name = test_info->name();
|
||||
std::replace(test_name.begin(), test_name.end(), '/', '_');
|
||||
const std::string temp_filename =
|
||||
test::OutputPath() + "RtcEventLogTest_" + test_name;
|
||||
test::OutputPath() + test_info->test_case_name() + test_info->name();
|
||||
|
||||
rtc::ScopedFakeClock fake_clock;
|
||||
fake_clock.SetTimeMicros(prng.Rand<uint32_t>());
|
||||
@ -438,8 +432,7 @@ void RtcEventLogSession::WriteSession() {
|
||||
fake_clock.AdvanceTimeMicros(prng.Rand(1, 1000));
|
||||
if (i == event_types.size() / 2)
|
||||
log_dumper->StartLogging(
|
||||
rtc::MakeUnique<RtcEventLogOutputFile>(temp_filename, 10000000),
|
||||
output_period_ms);
|
||||
rtc::MakeUnique<RtcEventLogOutputFile>(temp_filename, 10000000));
|
||||
switch (event_types[i]) {
|
||||
case EventType::kIncomingRtp:
|
||||
RTC_CHECK(incoming_rtp_written < incoming_rtp_packets.size());
|
||||
@ -523,19 +516,18 @@ void RtcEventLogSession::WriteSession() {
|
||||
|
||||
// Read the file and verify that what we read back from the event log is the
|
||||
// same as what we wrote down.
|
||||
void RtcEventLogSession::ReadAndVerifySession() {
|
||||
void RtcEventLogSessionDescription::ReadAndVerifySession() {
|
||||
// Find the name of the current test, in order to use it as a temporary
|
||||
// filename.
|
||||
auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
|
||||
std::string test_name = test_info->name();
|
||||
std::replace(test_name.begin(), test_name.end(), '/', '_');
|
||||
const std::string temp_filename =
|
||||
test::OutputPath() + "RtcEventLogTest_" + test_name;
|
||||
test::OutputPath() + test_info->test_case_name() + test_info->name();
|
||||
|
||||
// Read the generated file from disk.
|
||||
ParsedRtcEventLog parsed_log;
|
||||
ASSERT_TRUE(parsed_log.ParseFile(temp_filename));
|
||||
EXPECT_GE(5000u, event_types.size() + 2); // The events must fit.
|
||||
EXPECT_GE(1000u, event_types.size() +
|
||||
2); // The events must fit in the message queue.
|
||||
EXPECT_EQ(event_types.size() + 2, parsed_log.GetNumberOfEvents());
|
||||
|
||||
size_t incoming_rtp_read = 0;
|
||||
@ -638,7 +630,7 @@ void RtcEventLogSession::ReadAndVerifySession() {
|
||||
remove(temp_filename.c_str());
|
||||
}
|
||||
|
||||
void RtcEventLogSession::PrintExpectedEvents(std::ostream& stream) {
|
||||
void RtcEventLogSessionDescription::PrintExpectedEvents(std::ostream& stream) {
|
||||
for (size_t i = 0; i < event_types.size(); i++) {
|
||||
auto it = event_type_to_string.find(event_types[i]);
|
||||
RTC_CHECK(it != event_type_to_string.end());
|
||||
@ -657,122 +649,72 @@ void PrintActualEvents(const ParsedRtcEventLog& parsed_log,
|
||||
stream << std::endl;
|
||||
}
|
||||
|
||||
TEST_P(RtcEventLogSession, LogSessionAndReadBack) {
|
||||
TEST(RtcEventLogTest, LogSessionAndReadBack) {
|
||||
RtpHeaderExtensionMap extensions;
|
||||
GenerateSessionDescription(3, // Number of incoming RTP packets.
|
||||
2, // Number of outgoing RTP packets.
|
||||
1, // Number of incoming RTCP packets.
|
||||
1, // Number of outgoing RTCP packets.
|
||||
0, // Number of playout events.
|
||||
0, // Number of BWE loss events.
|
||||
0, // Number of BWE delay events.
|
||||
extensions, // No extensions.
|
||||
0); // Number of contributing sources.
|
||||
WriteSession();
|
||||
ReadAndVerifySession();
|
||||
RtcEventLogSessionDescription session(321 /*Random seed*/);
|
||||
session.GenerateSessionDescription(3, // Number of incoming RTP packets.
|
||||
2, // Number of outgoing RTP packets.
|
||||
1, // Number of incoming RTCP packets.
|
||||
1, // Number of outgoing RTCP packets.
|
||||
0, // Number of playout events.
|
||||
0, // Number of BWE loss events.
|
||||
0, // Number of BWE delay events.
|
||||
extensions, // No extensions.
|
||||
0); // Number of contributing sources.
|
||||
session.WriteSession();
|
||||
session.ReadAndVerifySession();
|
||||
}
|
||||
|
||||
TEST_P(RtcEventLogSession, LogSessionAndReadBackWith2Extensions) {
|
||||
TEST(RtcEventLogTest, LogSessionAndReadBackWith2Extensions) {
|
||||
RtpHeaderExtensionMap extensions;
|
||||
extensions.Register(kRtpExtensionAbsoluteSendTime,
|
||||
kAbsoluteSendTimeExtensionId);
|
||||
extensions.Register(kRtpExtensionTransportSequenceNumber,
|
||||
kTransportSequenceNumberExtensionId);
|
||||
GenerateSessionDescription(4, 4, 1, 1, 0, 0, 0, extensions, 0);
|
||||
WriteSession();
|
||||
ReadAndVerifySession();
|
||||
RtcEventLogSessionDescription session(3141592653u /*Random seed*/);
|
||||
session.GenerateSessionDescription(4, 4, 1, 1, 0, 0, 0, extensions, 0);
|
||||
session.WriteSession();
|
||||
session.ReadAndVerifySession();
|
||||
}
|
||||
|
||||
TEST_P(RtcEventLogSession, LogSessionAndReadBackWithAllExtensions) {
|
||||
TEST(RtcEventLogTest, LogSessionAndReadBackWithAllExtensions) {
|
||||
RtpHeaderExtensionMap extensions;
|
||||
for (uint32_t i = 0; i < kNumExtensions; i++) {
|
||||
extensions.Register(kExtensionTypes[i], kExtensionIds[i]);
|
||||
}
|
||||
GenerateSessionDescription(5, 4, 1, 1, 3, 2, 2, extensions, 2);
|
||||
WriteSession();
|
||||
ReadAndVerifySession();
|
||||
RtcEventLogSessionDescription session(2718281828u /*Random seed*/);
|
||||
session.GenerateSessionDescription(5, 4, 1, 1, 3, 2, 2, extensions, 2);
|
||||
session.WriteSession();
|
||||
session.ReadAndVerifySession();
|
||||
}
|
||||
|
||||
TEST_P(RtcEventLogSession, LogLongSessionAndReadBack) {
|
||||
RtpHeaderExtensionMap extensions;
|
||||
for (uint32_t i = 0; i < kNumExtensions; i++) {
|
||||
extensions.Register(kExtensionTypes[i], kExtensionIds[i]);
|
||||
TEST(RtcEventLogTest, LogSessionAndReadBackAllCombinations) {
|
||||
// Try all combinations of header extensions and up to 2 CSRCS.
|
||||
for (uint32_t extension_selection = 0;
|
||||
extension_selection < (1u << kNumExtensions); extension_selection++) {
|
||||
RtpHeaderExtensionMap extensions;
|
||||
for (uint32_t i = 0; i < kNumExtensions; i++) {
|
||||
if (extension_selection & (1u << i)) {
|
||||
extensions.Register(kExtensionTypes[i], kExtensionIds[i]);
|
||||
}
|
||||
}
|
||||
for (uint32_t csrcs_count = 0; csrcs_count < 3; csrcs_count++) {
|
||||
RtcEventLogSessionDescription session(extension_selection * 3 +
|
||||
csrcs_count + 1 /*Random seed*/);
|
||||
session.GenerateSessionDescription(
|
||||
2 + extension_selection, // Number of incoming RTP packets.
|
||||
2 + extension_selection, // Number of outgoing RTP packets.
|
||||
1 + csrcs_count, // Number of incoming RTCP packets.
|
||||
1 + csrcs_count, // Number of outgoing RTCP packets.
|
||||
3 + csrcs_count, // Number of playout events.
|
||||
1 + csrcs_count, // Number of BWE loss events.
|
||||
2 + csrcs_count, // Number of BWE delay events.
|
||||
extensions, // Bit vector choosing extensions.
|
||||
csrcs_count); // Number of contributing sources.
|
||||
session.WriteSession();
|
||||
session.ReadAndVerifySession();
|
||||
}
|
||||
}
|
||||
GenerateSessionDescription(1000, 1000, 250, 250, 200, 100, 100, extensions,
|
||||
1);
|
||||
WriteSession();
|
||||
ReadAndVerifySession();
|
||||
}
|
||||
|
||||
TEST(RtcEventLogTest, CircularBufferKeepsMostRecentEvents) {
|
||||
constexpr size_t kNumEvents = 20000;
|
||||
constexpr int64_t kStartTime = 1000000;
|
||||
|
||||
auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
|
||||
std::string test_name = test_info->name();
|
||||
std::replace(test_name.begin(), test_name.end(), '/', '_');
|
||||
const std::string temp_filename =
|
||||
test::OutputPath() + "RtcEventLogTest_" + test_name;
|
||||
|
||||
rtc::ScopedFakeClock fake_clock;
|
||||
fake_clock.SetTimeMicros(kStartTime);
|
||||
|
||||
// When log_dumper goes out of scope, it causes the log file to be flushed
|
||||
// to disk.
|
||||
std::unique_ptr<RtcEventLog> log_dumper(
|
||||
RtcEventLog::Create(RtcEventLog::EncodingType::Legacy));
|
||||
|
||||
for (size_t i = 0; i < kNumEvents; i++) {
|
||||
// The purpose of the test is to verify that the log can handle
|
||||
// more events than what fits in the internal circular buffer. The exact
|
||||
// type of events does not matter so we chose AudioPlayouts for simplicity.
|
||||
// We use the index as an ssrc to get a strict relationship between the ssrc
|
||||
// and the timestamp. We use this for some basic consistency checks when we
|
||||
// read back.
|
||||
log_dumper->Log(rtc::MakeUnique<RtcEventAudioPlayout>(i));
|
||||
fake_clock.AdvanceTimeMicros(10000);
|
||||
}
|
||||
log_dumper->StartLogging(
|
||||
rtc::MakeUnique<RtcEventLogOutputFile>(temp_filename, 10000000),
|
||||
RtcEventLog::kImmediateOutput);
|
||||
log_dumper->StopLogging();
|
||||
|
||||
// Read the generated file from disk.
|
||||
ParsedRtcEventLog parsed_log;
|
||||
ASSERT_TRUE(parsed_log.ParseFile(temp_filename));
|
||||
// If the following fails, it probably means that kNumEvents isn't larger
|
||||
// than the size of the cyclic buffer in the event log. Try increasing
|
||||
// kNumEvents.
|
||||
EXPECT_LT(parsed_log.GetNumberOfEvents(), kNumEvents);
|
||||
// We expect a start event, some number of playouts events and a stop event.
|
||||
EXPECT_GT(parsed_log.GetNumberOfEvents(), 2u);
|
||||
|
||||
RtcEventLogTestHelper::VerifyLogStartEvent(parsed_log, 0);
|
||||
rtc::Optional<int64_t> last_timestamp;
|
||||
rtc::Optional<uint32_t> last_ssrc;
|
||||
for (size_t i = 1; i < parsed_log.GetNumberOfEvents() - 1; i++) {
|
||||
EXPECT_EQ(parsed_log.GetEventType(i),
|
||||
ParsedRtcEventLog::EventType::AUDIO_PLAYOUT_EVENT);
|
||||
uint32_t ssrc;
|
||||
parsed_log.GetAudioPlayout(i, &ssrc);
|
||||
int64_t timestamp = parsed_log.GetTimestamp(i);
|
||||
EXPECT_LT(ssrc, kNumEvents);
|
||||
EXPECT_EQ(static_cast<int64_t>(kStartTime + 10000 * ssrc), timestamp);
|
||||
if (last_ssrc)
|
||||
EXPECT_EQ(ssrc, *last_ssrc + 1);
|
||||
if (last_timestamp)
|
||||
EXPECT_EQ(timestamp, *last_timestamp + 10000);
|
||||
last_ssrc = ssrc;
|
||||
last_timestamp = timestamp;
|
||||
}
|
||||
RtcEventLogTestHelper::VerifyLogEndEvent(parsed_log,
|
||||
parsed_log.GetNumberOfEvents() - 1);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
RtcEventLogTest,
|
||||
RtcEventLogSession,
|
||||
::testing::Combine(::testing::Values(1234567, 7654321),
|
||||
::testing::Values(RtcEventLog::kImmediateOutput, 1, 5)));
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -1934,22 +1934,14 @@ bool PeerConnection::StartRtcEventLog(rtc::PlatformFile file,
|
||||
|
||||
bool PeerConnection::StartRtcEventLog(
|
||||
std::unique_ptr<RtcEventLogOutput> output) {
|
||||
return StartRtcEventLog(std::move(output), RtcEventLog::kImmediateOutput);
|
||||
}
|
||||
|
||||
bool PeerConnection::StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output,
|
||||
int64_t output_period_ms) {
|
||||
// TODO(eladalon): In C++14, this can be done with a lambda.
|
||||
struct Functor {
|
||||
bool operator()() {
|
||||
return pc->StartRtcEventLog_w(std::move(output), output_period_ms);
|
||||
}
|
||||
bool operator()() { return pc->StartRtcEventLog_w(std::move(output)); }
|
||||
PeerConnection* const pc;
|
||||
std::unique_ptr<RtcEventLogOutput> output;
|
||||
const int64_t output_period_ms;
|
||||
};
|
||||
return worker_thread()->Invoke<bool>(
|
||||
RTC_FROM_HERE, Functor{this, std::move(output), output_period_ms});
|
||||
return worker_thread()->Invoke<bool>(RTC_FROM_HERE,
|
||||
Functor{this, std::move(output)});
|
||||
}
|
||||
|
||||
void PeerConnection::StopRtcEventLog() {
|
||||
@ -3145,12 +3137,11 @@ MetricsObserverInterface* PeerConnection::metrics_observer() const {
|
||||
}
|
||||
|
||||
bool PeerConnection::StartRtcEventLog_w(
|
||||
std::unique_ptr<RtcEventLogOutput> output,
|
||||
int64_t output_period_ms) {
|
||||
std::unique_ptr<RtcEventLogOutput> output) {
|
||||
if (!event_log_) {
|
||||
return false;
|
||||
}
|
||||
return event_log_->StartLogging(std::move(output), output_period_ms);
|
||||
return event_log_->StartLogging(std::move(output));
|
||||
}
|
||||
|
||||
void PeerConnection::StopRtcEventLog_w() {
|
||||
|
||||
@ -178,10 +178,7 @@ class PeerConnection : public PeerConnectionInterface,
|
||||
|
||||
RTC_DEPRECATED bool StartRtcEventLog(rtc::PlatformFile file,
|
||||
int64_t max_size_bytes) override;
|
||||
RTC_DEPRECATED bool StartRtcEventLog(
|
||||
std::unique_ptr<RtcEventLogOutput> output) override;
|
||||
bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output,
|
||||
int64_t output_period_ms) override;
|
||||
bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output) override;
|
||||
void StopRtcEventLog() override;
|
||||
|
||||
void Close() override;
|
||||
@ -494,8 +491,7 @@ class PeerConnection : public PeerConnectionInterface,
|
||||
|
||||
// Starts output of an RTC event log to the given output object.
|
||||
// This function should only be called from the worker thread.
|
||||
bool StartRtcEventLog_w(std::unique_ptr<RtcEventLogOutput> output,
|
||||
int64_t output_period_ms);
|
||||
bool StartRtcEventLog_w(std::unique_ptr<RtcEventLogOutput> output);
|
||||
|
||||
// Stops recording an RTC event log.
|
||||
// This function should only be called from the worker thread.
|
||||
|
||||
@ -1801,11 +1801,9 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
|
||||
|
||||
if (!params.logging.rtc_event_log_name.empty()) {
|
||||
event_log_ = RtcEventLog::Create(clock_, RtcEventLog::EncodingType::Legacy);
|
||||
std::unique_ptr<RtcEventLogOutputFile> output(
|
||||
rtc::MakeUnique<RtcEventLogOutputFile>(
|
||||
bool event_log_started =
|
||||
event_log_->StartLogging(rtc::MakeUnique<RtcEventLogOutputFile>(
|
||||
params.logging.rtc_event_log_name, RtcEventLog::kUnlimitedOutput));
|
||||
bool event_log_started = event_log_->StartLogging(
|
||||
std::move(output), RtcEventLog::kImmediateOutput);
|
||||
RTC_DCHECK(event_log_started);
|
||||
}
|
||||
|
||||
|
||||
@ -65,8 +65,7 @@ class RtcEventLogProxy final : public webrtc::RtcEventLog {
|
||||
public:
|
||||
RtcEventLogProxy() : event_log_(nullptr) {}
|
||||
|
||||
bool StartLogging(std::unique_ptr<RtcEventLogOutput> output,
|
||||
int64_t output_period_ms) override {
|
||||
bool StartLogging(std::unique_ptr<RtcEventLogOutput> output) override {
|
||||
RTC_NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user