2015-07-30 12:45:18 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by a BSD-style license
|
|
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
|
|
|
|
* in the file PATENTS. All contributing project authors may
|
|
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
2015-09-25 13:58:30 +02:00
|
|
|
#include "webrtc/call/rtc_event_log.h"
|
2015-07-30 12:45:18 +02:00
|
|
|
|
2016-04-22 12:40:37 -07:00
|
|
|
#include <limits>
|
2015-10-16 08:51:08 -07:00
|
|
|
#include <vector>
|
2015-07-30 12:45:18 +02:00
|
|
|
|
|
|
|
|
#include "webrtc/base/checks.h"
|
2016-04-22 12:40:37 -07:00
|
|
|
#include "webrtc/base/constructormagic.h"
|
|
|
|
|
#include "webrtc/base/event.h"
|
|
|
|
|
#include "webrtc/base/swap_queue.h"
|
|
|
|
|
#include "webrtc/base/thread_checker.h"
|
2015-07-30 12:45:18 +02:00
|
|
|
#include "webrtc/call.h"
|
2016-04-22 12:40:37 -07:00
|
|
|
#include "webrtc/call/rtc_event_log_helper_thread.h"
|
2015-11-06 09:00:18 -08:00
|
|
|
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
2015-09-04 03:39:42 -07:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
|
2015-11-06 09:00:18 -08:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
|
2015-10-28 18:17:40 +01:00
|
|
|
#include "webrtc/system_wrappers/include/clock.h"
|
|
|
|
|
#include "webrtc/system_wrappers/include/file_wrapper.h"
|
2016-04-22 12:40:37 -07:00
|
|
|
#include "webrtc/system_wrappers/include/logging.h"
|
2015-07-30 12:45:18 +02:00
|
|
|
|
|
|
|
|
#ifdef ENABLE_RTC_EVENT_LOG
|
|
|
|
|
// Files generated at build-time by the protobuf compiler.
|
|
|
|
|
#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
|
2015-09-25 13:58:30 +02:00
|
|
|
#include "external/webrtc/webrtc/call/rtc_event_log.pb.h"
|
2015-07-30 12:45:18 +02:00
|
|
|
#else
|
2015-09-25 13:58:30 +02:00
|
|
|
#include "webrtc/call/rtc_event_log.pb.h"
|
2015-07-30 12:45:18 +02:00
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace webrtc {
|
|
|
|
|
|
Revert of Move RtcEventLog object from inside VoiceEngine to Call. (patchset #16 id:420001 of https://codereview.webrtc.org/1748403002/ )
Reason for revert:
Reverting all CLs related to moving the eventlog, as they break Chromium tests.
Original issue's description:
> Move RtcEventLog object from inside VoiceEngine to Call.
>
> In addition to moving the logging object itself, this also moves the interface from PeerConnectionFactory to PeerConnection, which makes more sense for this functionality. An API parameter to set an upper limit to the size of the logfile is introduced.
> The old interface on PeerConnectionFactory is not removed in this CL, because it is called from Chrome, it will be removed after Chrome is updated to use the PeerConnection interface.
>
> BUG=webrtc:4741,webrtc:5603,chromium:609749
> R=solenberg@webrtc.org, stefan@webrtc.org, terelius@webrtc.org, tommi@webrtc.org
>
> Committed: https://crrev.com/1895526c6130e3d0e9b154f95079b8eda7567016
> Cr-Commit-Position: refs/heads/master@{#13321}
TBR=solenberg@webrtc.org,tommi@webrtc.org,stefan@webrtc.org,terelius@webrtc.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=webrtc:4741,webrtc:5603,chromium:609749
Review-Url: https://codereview.webrtc.org/2111813002
Cr-Commit-Position: refs/heads/master@{#13340}
2016-06-30 00:59:43 -07:00
|
|
|
#ifndef ENABLE_RTC_EVENT_LOG
|
|
|
|
|
|
|
|
|
|
// No-op implementation if flag is not set.
|
2016-04-22 12:40:37 -07:00
|
|
|
class RtcEventLogNullImpl final : public RtcEventLog {
|
2015-07-30 12:45:18 +02:00
|
|
|
public:
|
2016-04-22 12:40:37 -07:00
|
|
|
bool StartLogging(const std::string& file_name,
|
|
|
|
|
int64_t max_size_bytes) override {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
bool StartLogging(rtc::PlatformFile platform_file,
|
|
|
|
|
int64_t max_size_bytes) override {
|
2016-05-27 02:22:51 -07:00
|
|
|
// The platform_file is open and needs to be closed.
|
|
|
|
|
if (!rtc::ClosePlatformFile(platform_file)) {
|
|
|
|
|
LOG(LS_ERROR) << "Can't close file.";
|
|
|
|
|
}
|
2016-04-22 12:40:37 -07:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
void StopLogging() override {}
|
2015-07-30 12:45:18 +02:00
|
|
|
void LogVideoReceiveStreamConfig(
|
|
|
|
|
const VideoReceiveStream::Config& config) override {}
|
|
|
|
|
void LogVideoSendStreamConfig(
|
|
|
|
|
const VideoSendStream::Config& config) override {}
|
2016-01-21 05:42:04 -08:00
|
|
|
void LogRtpHeader(PacketDirection direction,
|
2015-07-30 12:45:18 +02:00
|
|
|
MediaType media_type,
|
|
|
|
|
const uint8_t* header,
|
2015-09-04 03:39:42 -07:00
|
|
|
size_t packet_length) override {}
|
2016-01-21 05:42:04 -08:00
|
|
|
void LogRtcpPacket(PacketDirection direction,
|
2015-07-30 12:45:18 +02:00
|
|
|
MediaType media_type,
|
|
|
|
|
const uint8_t* packet,
|
|
|
|
|
size_t length) override {}
|
2015-09-17 16:30:16 +02:00
|
|
|
void LogAudioPlayout(uint32_t ssrc) override {}
|
2015-11-05 12:02:15 -08:00
|
|
|
void LogBwePacketLossEvent(int32_t bitrate,
|
|
|
|
|
uint8_t fraction_loss,
|
|
|
|
|
int32_t total_packets) override {}
|
2015-07-30 12:45:18 +02:00
|
|
|
};
|
|
|
|
|
|
Revert of Move RtcEventLog object from inside VoiceEngine to Call. (patchset #16 id:420001 of https://codereview.webrtc.org/1748403002/ )
Reason for revert:
Reverting all CLs related to moving the eventlog, as they break Chromium tests.
Original issue's description:
> Move RtcEventLog object from inside VoiceEngine to Call.
>
> In addition to moving the logging object itself, this also moves the interface from PeerConnectionFactory to PeerConnection, which makes more sense for this functionality. An API parameter to set an upper limit to the size of the logfile is introduced.
> The old interface on PeerConnectionFactory is not removed in this CL, because it is called from Chrome, it will be removed after Chrome is updated to use the PeerConnection interface.
>
> BUG=webrtc:4741,webrtc:5603,chromium:609749
> R=solenberg@webrtc.org, stefan@webrtc.org, terelius@webrtc.org, tommi@webrtc.org
>
> Committed: https://crrev.com/1895526c6130e3d0e9b154f95079b8eda7567016
> Cr-Commit-Position: refs/heads/master@{#13321}
TBR=solenberg@webrtc.org,tommi@webrtc.org,stefan@webrtc.org,terelius@webrtc.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=webrtc:4741,webrtc:5603,chromium:609749
Review-Url: https://codereview.webrtc.org/2111813002
Cr-Commit-Position: refs/heads/master@{#13340}
2016-06-30 00:59:43 -07:00
|
|
|
#else // ENABLE_RTC_EVENT_LOG is defined
|
2015-07-30 12:45:18 +02:00
|
|
|
|
|
|
|
|
class RtcEventLogImpl final : public RtcEventLog {
|
|
|
|
|
public:
|
2016-04-22 12:40:37 -07:00
|
|
|
explicit RtcEventLogImpl(const Clock* clock);
|
|
|
|
|
~RtcEventLogImpl() override;
|
2015-10-16 08:51:08 -07:00
|
|
|
|
2016-04-22 12:40:37 -07:00
|
|
|
bool StartLogging(const std::string& file_name,
|
|
|
|
|
int64_t max_size_bytes) override;
|
|
|
|
|
bool StartLogging(rtc::PlatformFile platform_file,
|
|
|
|
|
int64_t max_size_bytes) override;
|
2015-07-30 12:45:18 +02:00
|
|
|
void StopLogging() override;
|
|
|
|
|
void LogVideoReceiveStreamConfig(
|
|
|
|
|
const VideoReceiveStream::Config& config) override;
|
|
|
|
|
void LogVideoSendStreamConfig(const VideoSendStream::Config& config) override;
|
2016-01-21 05:42:04 -08:00
|
|
|
void LogRtpHeader(PacketDirection direction,
|
2015-07-30 12:45:18 +02:00
|
|
|
MediaType media_type,
|
|
|
|
|
const uint8_t* header,
|
2015-09-04 03:39:42 -07:00
|
|
|
size_t packet_length) override;
|
2016-01-21 05:42:04 -08:00
|
|
|
void LogRtcpPacket(PacketDirection direction,
|
2015-07-30 12:45:18 +02:00
|
|
|
MediaType media_type,
|
|
|
|
|
const uint8_t* packet,
|
|
|
|
|
size_t length) override;
|
2015-09-17 16:30:16 +02:00
|
|
|
void LogAudioPlayout(uint32_t ssrc) override;
|
2015-11-05 12:02:15 -08:00
|
|
|
void LogBwePacketLossEvent(int32_t bitrate,
|
|
|
|
|
uint8_t fraction_loss,
|
|
|
|
|
int32_t total_packets) override;
|
2015-07-30 12:45:18 +02:00
|
|
|
|
|
|
|
|
private:
|
2016-06-08 07:20:29 -07:00
|
|
|
void StoreEvent(std::unique_ptr<rtclog::Event>* event);
|
|
|
|
|
|
2016-04-22 12:40:37 -07:00
|
|
|
// Message queue for passing control messages to the logging thread.
|
|
|
|
|
SwapQueue<RtcEventLogHelperThread::ControlMessage> message_queue_;
|
|
|
|
|
|
|
|
|
|
// Message queue for passing events to the logging thread.
|
|
|
|
|
SwapQueue<std::unique_ptr<rtclog::Event> > event_queue_;
|
|
|
|
|
|
2015-10-16 08:51:08 -07:00
|
|
|
const Clock* const clock_;
|
2016-04-22 12:40:37 -07:00
|
|
|
|
|
|
|
|
RtcEventLogHelperThread helper_thread_;
|
|
|
|
|
rtc::ThreadChecker thread_checker_;
|
|
|
|
|
|
|
|
|
|
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RtcEventLogImpl);
|
2015-07-30 12:45:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
// The functions in this namespace convert enums from the runtime format
|
|
|
|
|
// that the rest of the WebRtc project can use, to the corresponding
|
|
|
|
|
// serialized enum which is defined by the protobuf.
|
|
|
|
|
|
2015-10-02 02:36:56 -07:00
|
|
|
rtclog::VideoReceiveConfig_RtcpMode ConvertRtcpMode(RtcpMode rtcp_mode) {
|
2015-07-30 12:45:18 +02:00
|
|
|
switch (rtcp_mode) {
|
2015-10-02 02:36:56 -07:00
|
|
|
case RtcpMode::kCompound:
|
2015-07-30 12:45:18 +02:00
|
|
|
return rtclog::VideoReceiveConfig::RTCP_COMPOUND;
|
2015-10-02 02:36:56 -07:00
|
|
|
case RtcpMode::kReducedSize:
|
2015-07-30 12:45:18 +02:00
|
|
|
return rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE;
|
2015-10-02 02:36:56 -07:00
|
|
|
case RtcpMode::kOff:
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
return rtclog::VideoReceiveConfig::RTCP_COMPOUND;
|
2015-07-30 12:45:18 +02:00
|
|
|
}
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
return rtclog::VideoReceiveConfig::RTCP_COMPOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtclog::MediaType ConvertMediaType(MediaType media_type) {
|
|
|
|
|
switch (media_type) {
|
|
|
|
|
case MediaType::ANY:
|
|
|
|
|
return rtclog::MediaType::ANY;
|
|
|
|
|
case MediaType::AUDIO:
|
|
|
|
|
return rtclog::MediaType::AUDIO;
|
|
|
|
|
case MediaType::VIDEO:
|
|
|
|
|
return rtclog::MediaType::VIDEO;
|
|
|
|
|
case MediaType::DATA:
|
|
|
|
|
return rtclog::MediaType::DATA;
|
|
|
|
|
}
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
return rtclog::ANY;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-22 12:40:37 -07:00
|
|
|
// The RTP and RTCP buffers reserve space for twice the expected number of
|
|
|
|
|
// sent packets because they also contain received packets.
|
|
|
|
|
static const int kEventsPerSecond = 1000;
|
|
|
|
|
static const int kControlMessagesPerSecond = 10;
|
2015-10-16 08:51:08 -07:00
|
|
|
} // namespace
|
|
|
|
|
|
2015-07-30 12:45:18 +02:00
|
|
|
// RtcEventLogImpl member functions.
|
2016-04-22 12:40:37 -07:00
|
|
|
RtcEventLogImpl::RtcEventLogImpl(const Clock* clock)
|
|
|
|
|
// Allocate buffers for roughly one second of history.
|
|
|
|
|
: message_queue_(kControlMessagesPerSecond),
|
|
|
|
|
event_queue_(kEventsPerSecond),
|
|
|
|
|
clock_(clock),
|
|
|
|
|
helper_thread_(&message_queue_,
|
|
|
|
|
&event_queue_,
|
|
|
|
|
clock),
|
|
|
|
|
thread_checker_() {
|
|
|
|
|
thread_checker_.DetachFromThread();
|
2015-10-16 08:51:08 -07:00
|
|
|
}
|
|
|
|
|
|
2016-04-22 12:40:37 -07:00
|
|
|
RtcEventLogImpl::~RtcEventLogImpl() {
|
|
|
|
|
// The RtcEventLogHelperThread destructor closes the file
|
|
|
|
|
// and waits for the thread to terminate.
|
2015-10-16 08:51:08 -07:00
|
|
|
}
|
2015-07-30 12:45:18 +02:00
|
|
|
|
2016-04-22 12:40:37 -07:00
|
|
|
bool RtcEventLogImpl::StartLogging(const std::string& file_name,
|
|
|
|
|
int64_t max_size_bytes) {
|
|
|
|
|
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
|
|
|
|
RtcEventLogHelperThread::ControlMessage message;
|
|
|
|
|
message.message_type = RtcEventLogHelperThread::ControlMessage::START_FILE;
|
2016-05-13 08:30:39 -07:00
|
|
|
message.max_size_bytes = max_size_bytes <= 0
|
|
|
|
|
? std::numeric_limits<int64_t>::max()
|
|
|
|
|
: max_size_bytes;
|
2016-04-22 12:40:37 -07:00
|
|
|
message.start_time = clock_->TimeInMicroseconds();
|
|
|
|
|
message.stop_time = std::numeric_limits<int64_t>::max();
|
|
|
|
|
message.file.reset(FileWrapper::Create());
|
FileWrapper[Impl] modifications and actually remove the "Impl" class.
This is a somewhat involved refactoring of this class. Here's an overview of the changes:
* FileWrapper can now be used as a regular class and instances allocated on the stack.
* The type now has support for move semantics and copy isn't allowed.
* New public ctor with FILE* that can be used instead of OpenFromFileHandle.
* New static Open() method. The intent of this is to allow opening a file and getting back a FileWrapper instance. Using this method instead of Create(), will allow us in the future to make the FILE* member pointer, to be const and simplify threading (get rid of the lock).
* Rename the Open() method to is_open() and make it inline.
* The FileWrapper interface is no longer a pure virtual interface. There's only one implementation so there's no need to go through a vtable for everything.
* Functionality offered by the class, is now reduced. No support for looping (not clear if that was actually useful to users of that flag), no need to implement the 'read_only_' functionality in the class, since file APIs implement that already, no support for *not* managing the file handle (this wasn't used). OpenFromFileHandle always "manages" the file.
* Delete the unused WriteText() method and don't support opening files in text mode. Text mode is only different on Windows and on Windows it translates \n to \r\n, which means that files such as log files, could have a slightly different format on Windows than other platforms. Besides, tools on Windows can handle UNIX line endings.
* Remove FileName(), change Trace code to manage its own path.
* Rename id_ member variable to file_.
* Removed the open_ member variable since the same functionality can be gotten from just checking the file pointer.
* Don't call CloseFile inside of Write. Write shouldn't be changing the state of the class beyond just attempting to write.
* Remove concept of looping from FileWrapper and never close inside of Read()
* Changed stream base classes to inherit from a common base class instead of both defining the Rewind method. Ultimately, Id' like to remove these interfaces and just have FileWrapper.
* Remove read_only param from OpenFromFileHandle
* Renamed size_in_bytes_ to position_, since it gets set to 0 when Rewind() is called (and the size actually does not change).
* Switch out rw lock for CriticalSection. The r/w lock was only used for reading when checking the open_ flag.
BUG=
Review-Url: https://codereview.webrtc.org/2054373002
Cr-Commit-Position: refs/heads/master@{#13155}
2016-06-15 10:30:14 -07:00
|
|
|
if (!message.file->OpenFile(file_name.c_str(), false)) {
|
2016-05-27 02:22:51 -07:00
|
|
|
LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
|
2016-04-22 12:40:37 -07:00
|
|
|
return false;
|
2015-07-30 12:45:18 +02:00
|
|
|
}
|
2016-04-22 12:40:37 -07:00
|
|
|
if (!message_queue_.Insert(&message)) {
|
2016-05-27 02:22:51 -07:00
|
|
|
LOG(LS_ERROR) << "Message queue full. Can't start logging.";
|
2016-04-22 12:40:37 -07:00
|
|
|
return false;
|
2015-07-30 12:45:18 +02:00
|
|
|
}
|
2016-06-08 07:20:29 -07:00
|
|
|
helper_thread_.SignalNewEvent();
|
2016-05-27 02:22:51 -07:00
|
|
|
LOG(LS_INFO) << "Starting WebRTC event log.";
|
2016-04-22 12:40:37 -07:00
|
|
|
return true;
|
2015-10-16 02:22:18 -07:00
|
|
|
}
|
|
|
|
|
|
2016-04-22 12:40:37 -07:00
|
|
|
bool RtcEventLogImpl::StartLogging(rtc::PlatformFile platform_file,
|
|
|
|
|
int64_t max_size_bytes) {
|
|
|
|
|
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
|
|
|
|
RtcEventLogHelperThread::ControlMessage message;
|
|
|
|
|
message.message_type = RtcEventLogHelperThread::ControlMessage::START_FILE;
|
2016-05-13 08:30:39 -07:00
|
|
|
message.max_size_bytes = max_size_bytes <= 0
|
|
|
|
|
? std::numeric_limits<int64_t>::max()
|
|
|
|
|
: max_size_bytes;
|
2016-04-22 12:40:37 -07:00
|
|
|
message.start_time = clock_->TimeInMicroseconds();
|
|
|
|
|
message.stop_time = std::numeric_limits<int64_t>::max();
|
|
|
|
|
message.file.reset(FileWrapper::Create());
|
|
|
|
|
FILE* file_handle = rtc::FdopenPlatformFileForWriting(platform_file);
|
|
|
|
|
if (!file_handle) {
|
2016-05-27 02:22:51 -07:00
|
|
|
LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
|
|
|
|
|
// Even though we failed to open a FILE*, the platform_file is still open
|
|
|
|
|
// and needs to be closed.
|
|
|
|
|
if (!rtc::ClosePlatformFile(platform_file)) {
|
|
|
|
|
LOG(LS_ERROR) << "Can't close file.";
|
|
|
|
|
}
|
2016-04-22 12:40:37 -07:00
|
|
|
return false;
|
2015-10-16 02:22:18 -07:00
|
|
|
}
|
FileWrapper[Impl] modifications and actually remove the "Impl" class.
This is a somewhat involved refactoring of this class. Here's an overview of the changes:
* FileWrapper can now be used as a regular class and instances allocated on the stack.
* The type now has support for move semantics and copy isn't allowed.
* New public ctor with FILE* that can be used instead of OpenFromFileHandle.
* New static Open() method. The intent of this is to allow opening a file and getting back a FileWrapper instance. Using this method instead of Create(), will allow us in the future to make the FILE* member pointer, to be const and simplify threading (get rid of the lock).
* Rename the Open() method to is_open() and make it inline.
* The FileWrapper interface is no longer a pure virtual interface. There's only one implementation so there's no need to go through a vtable for everything.
* Functionality offered by the class, is now reduced. No support for looping (not clear if that was actually useful to users of that flag), no need to implement the 'read_only_' functionality in the class, since file APIs implement that already, no support for *not* managing the file handle (this wasn't used). OpenFromFileHandle always "manages" the file.
* Delete the unused WriteText() method and don't support opening files in text mode. Text mode is only different on Windows and on Windows it translates \n to \r\n, which means that files such as log files, could have a slightly different format on Windows than other platforms. Besides, tools on Windows can handle UNIX line endings.
* Remove FileName(), change Trace code to manage its own path.
* Rename id_ member variable to file_.
* Removed the open_ member variable since the same functionality can be gotten from just checking the file pointer.
* Don't call CloseFile inside of Write. Write shouldn't be changing the state of the class beyond just attempting to write.
* Remove concept of looping from FileWrapper and never close inside of Read()
* Changed stream base classes to inherit from a common base class instead of both defining the Rewind method. Ultimately, Id' like to remove these interfaces and just have FileWrapper.
* Remove read_only param from OpenFromFileHandle
* Renamed size_in_bytes_ to position_, since it gets set to 0 when Rewind() is called (and the size actually does not change).
* Switch out rw lock for CriticalSection. The r/w lock was only used for reading when checking the open_ flag.
BUG=
Review-Url: https://codereview.webrtc.org/2054373002
Cr-Commit-Position: refs/heads/master@{#13155}
2016-06-15 10:30:14 -07:00
|
|
|
if (!message.file->OpenFromFileHandle(file_handle)) {
|
2016-05-27 02:22:51 -07:00
|
|
|
LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
|
2015-10-16 02:22:18 -07:00
|
|
|
return false;
|
|
|
|
|
}
|
2016-04-22 12:40:37 -07:00
|
|
|
if (!message_queue_.Insert(&message)) {
|
2016-05-27 02:22:51 -07:00
|
|
|
LOG(LS_ERROR) << "Message queue full. Can't start logging.";
|
2015-10-16 02:22:18 -07:00
|
|
|
return false;
|
|
|
|
|
}
|
2016-06-08 07:20:29 -07:00
|
|
|
helper_thread_.SignalNewEvent();
|
2016-05-27 02:22:51 -07:00
|
|
|
LOG(LS_INFO) << "Starting WebRTC event log.";
|
2015-10-16 02:22:18 -07:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-30 12:45:18 +02:00
|
|
|
void RtcEventLogImpl::StopLogging() {
|
2016-04-22 12:40:37 -07:00
|
|
|
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
|
|
|
|
RtcEventLogHelperThread::ControlMessage message;
|
|
|
|
|
message.message_type = RtcEventLogHelperThread::ControlMessage::STOP_FILE;
|
|
|
|
|
message.stop_time = clock_->TimeInMicroseconds();
|
|
|
|
|
while (!message_queue_.Insert(&message)) {
|
|
|
|
|
// TODO(terelius): We would like to have a blocking Insert function in the
|
|
|
|
|
// SwapQueue, but for the time being we will just clear any previous
|
|
|
|
|
// messages.
|
|
|
|
|
// Since StopLogging waits for the thread, it is essential that we don't
|
|
|
|
|
// clear any STOP_FILE messages. To ensure that there is only one call at a
|
|
|
|
|
// time, we require that all calls to StopLogging are made on the same
|
|
|
|
|
// thread.
|
2016-05-27 02:22:51 -07:00
|
|
|
LOG(LS_ERROR) << "Message queue full. Clearing queue to stop logging.";
|
2016-04-22 12:40:37 -07:00
|
|
|
message_queue_.Clear();
|
|
|
|
|
}
|
2016-05-27 02:22:51 -07:00
|
|
|
LOG(LS_INFO) << "Stopping WebRTC event log.";
|
2016-06-08 07:20:29 -07:00
|
|
|
helper_thread_.WaitForFileFinished();
|
2015-07-30 12:45:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RtcEventLogImpl::LogVideoReceiveStreamConfig(
|
|
|
|
|
const VideoReceiveStream::Config& config) {
|
2016-04-22 12:40:37 -07:00
|
|
|
std::unique_ptr<rtclog::Event> event(new rtclog::Event());
|
|
|
|
|
event->set_timestamp_us(clock_->TimeInMicroseconds());
|
|
|
|
|
event->set_type(rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT);
|
2015-07-30 12:45:18 +02:00
|
|
|
|
|
|
|
|
rtclog::VideoReceiveConfig* receiver_config =
|
2016-04-22 12:40:37 -07:00
|
|
|
event->mutable_video_receiver_config();
|
2015-07-30 12:45:18 +02:00
|
|
|
receiver_config->set_remote_ssrc(config.rtp.remote_ssrc);
|
|
|
|
|
receiver_config->set_local_ssrc(config.rtp.local_ssrc);
|
|
|
|
|
|
|
|
|
|
receiver_config->set_rtcp_mode(ConvertRtcpMode(config.rtp.rtcp_mode));
|
|
|
|
|
receiver_config->set_remb(config.rtp.remb);
|
|
|
|
|
|
|
|
|
|
for (const auto& kv : config.rtp.rtx) {
|
|
|
|
|
rtclog::RtxMap* rtx = receiver_config->add_rtx_map();
|
|
|
|
|
rtx->set_payload_type(kv.first);
|
|
|
|
|
rtx->mutable_config()->set_rtx_ssrc(kv.second.ssrc);
|
|
|
|
|
rtx->mutable_config()->set_rtx_payload_type(kv.second.payload_type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto& e : config.rtp.extensions) {
|
|
|
|
|
rtclog::RtpHeaderExtension* extension =
|
|
|
|
|
receiver_config->add_header_extensions();
|
2016-05-26 11:24:55 -07:00
|
|
|
extension->set_name(e.uri);
|
2015-07-30 12:45:18 +02:00
|
|
|
extension->set_id(e.id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto& d : config.decoders) {
|
|
|
|
|
rtclog::DecoderConfig* decoder = receiver_config->add_decoders();
|
|
|
|
|
decoder->set_name(d.payload_name);
|
|
|
|
|
decoder->set_payload_type(d.payload_type);
|
|
|
|
|
}
|
2016-06-08 07:20:29 -07:00
|
|
|
StoreEvent(&event);
|
2015-07-30 12:45:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RtcEventLogImpl::LogVideoSendStreamConfig(
|
|
|
|
|
const VideoSendStream::Config& config) {
|
2016-04-22 12:40:37 -07:00
|
|
|
std::unique_ptr<rtclog::Event> event(new rtclog::Event());
|
|
|
|
|
event->set_timestamp_us(clock_->TimeInMicroseconds());
|
|
|
|
|
event->set_type(rtclog::Event::VIDEO_SENDER_CONFIG_EVENT);
|
2015-07-30 12:45:18 +02:00
|
|
|
|
2016-04-22 12:40:37 -07:00
|
|
|
rtclog::VideoSendConfig* sender_config = event->mutable_video_sender_config();
|
2015-07-30 12:45:18 +02:00
|
|
|
|
|
|
|
|
for (const auto& ssrc : config.rtp.ssrcs) {
|
|
|
|
|
sender_config->add_ssrcs(ssrc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto& e : config.rtp.extensions) {
|
|
|
|
|
rtclog::RtpHeaderExtension* extension =
|
|
|
|
|
sender_config->add_header_extensions();
|
2016-05-26 11:24:55 -07:00
|
|
|
extension->set_name(e.uri);
|
2015-07-30 12:45:18 +02:00
|
|
|
extension->set_id(e.id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto& rtx_ssrc : config.rtp.rtx.ssrcs) {
|
|
|
|
|
sender_config->add_rtx_ssrcs(rtx_ssrc);
|
|
|
|
|
}
|
|
|
|
|
sender_config->set_rtx_payload_type(config.rtp.rtx.payload_type);
|
|
|
|
|
|
|
|
|
|
rtclog::EncoderConfig* encoder = sender_config->mutable_encoder();
|
|
|
|
|
encoder->set_name(config.encoder_settings.payload_name);
|
|
|
|
|
encoder->set_payload_type(config.encoder_settings.payload_type);
|
2016-06-08 07:20:29 -07:00
|
|
|
StoreEvent(&event);
|
2015-07-30 12:45:18 +02:00
|
|
|
}
|
|
|
|
|
|
2016-01-21 05:42:04 -08:00
|
|
|
void RtcEventLogImpl::LogRtpHeader(PacketDirection direction,
|
2015-07-30 12:45:18 +02:00
|
|
|
MediaType media_type,
|
|
|
|
|
const uint8_t* header,
|
2015-09-04 03:39:42 -07:00
|
|
|
size_t packet_length) {
|
|
|
|
|
// Read header length (in bytes) from packet data.
|
|
|
|
|
if (packet_length < 12u) {
|
|
|
|
|
return; // Don't read outside the packet.
|
|
|
|
|
}
|
|
|
|
|
const bool x = (header[0] & 0x10) != 0;
|
|
|
|
|
const uint8_t cc = header[0] & 0x0f;
|
|
|
|
|
size_t header_length = 12u + cc * 4u;
|
|
|
|
|
|
|
|
|
|
if (x) {
|
|
|
|
|
if (packet_length < 12u + cc * 4u + 4u) {
|
|
|
|
|
return; // Don't read outside the packet.
|
|
|
|
|
}
|
|
|
|
|
size_t x_len = ByteReader<uint16_t>::ReadBigEndian(header + 14 + cc * 4);
|
|
|
|
|
header_length += (x_len + 1) * 4;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-22 12:40:37 -07:00
|
|
|
std::unique_ptr<rtclog::Event> rtp_event(new rtclog::Event());
|
|
|
|
|
rtp_event->set_timestamp_us(clock_->TimeInMicroseconds());
|
|
|
|
|
rtp_event->set_type(rtclog::Event::RTP_EVENT);
|
|
|
|
|
rtp_event->mutable_rtp_packet()->set_incoming(direction == kIncomingPacket);
|
|
|
|
|
rtp_event->mutable_rtp_packet()->set_type(ConvertMediaType(media_type));
|
|
|
|
|
rtp_event->mutable_rtp_packet()->set_packet_length(packet_length);
|
|
|
|
|
rtp_event->mutable_rtp_packet()->set_header(header, header_length);
|
2016-06-08 07:20:29 -07:00
|
|
|
StoreEvent(&rtp_event);
|
2015-07-30 12:45:18 +02:00
|
|
|
}
|
|
|
|
|
|
2016-01-21 05:42:04 -08:00
|
|
|
void RtcEventLogImpl::LogRtcpPacket(PacketDirection direction,
|
2015-07-30 12:45:18 +02:00
|
|
|
MediaType media_type,
|
|
|
|
|
const uint8_t* packet,
|
|
|
|
|
size_t length) {
|
2016-04-22 12:40:37 -07:00
|
|
|
std::unique_ptr<rtclog::Event> rtcp_event(new rtclog::Event());
|
|
|
|
|
rtcp_event->set_timestamp_us(clock_->TimeInMicroseconds());
|
|
|
|
|
rtcp_event->set_type(rtclog::Event::RTCP_EVENT);
|
|
|
|
|
rtcp_event->mutable_rtcp_packet()->set_incoming(direction == kIncomingPacket);
|
|
|
|
|
rtcp_event->mutable_rtcp_packet()->set_type(ConvertMediaType(media_type));
|
2015-11-06 09:00:18 -08:00
|
|
|
|
|
|
|
|
RTCPUtility::RtcpCommonHeader header;
|
|
|
|
|
const uint8_t* block_begin = packet;
|
|
|
|
|
const uint8_t* packet_end = packet + length;
|
|
|
|
|
RTC_DCHECK(length <= IP_PACKET_SIZE);
|
|
|
|
|
uint8_t buffer[IP_PACKET_SIZE];
|
|
|
|
|
uint32_t buffer_length = 0;
|
|
|
|
|
while (block_begin < packet_end) {
|
|
|
|
|
if (!RtcpParseCommonHeader(block_begin, packet_end - block_begin,
|
|
|
|
|
&header)) {
|
|
|
|
|
break; // Incorrect message header.
|
|
|
|
|
}
|
|
|
|
|
uint32_t block_size = header.BlockSize();
|
|
|
|
|
switch (header.packet_type) {
|
|
|
|
|
case RTCPUtility::PT_SR:
|
|
|
|
|
FALLTHROUGH();
|
|
|
|
|
case RTCPUtility::PT_RR:
|
|
|
|
|
FALLTHROUGH();
|
|
|
|
|
case RTCPUtility::PT_BYE:
|
|
|
|
|
FALLTHROUGH();
|
|
|
|
|
case RTCPUtility::PT_IJ:
|
|
|
|
|
FALLTHROUGH();
|
|
|
|
|
case RTCPUtility::PT_RTPFB:
|
|
|
|
|
FALLTHROUGH();
|
|
|
|
|
case RTCPUtility::PT_PSFB:
|
|
|
|
|
FALLTHROUGH();
|
|
|
|
|
case RTCPUtility::PT_XR:
|
|
|
|
|
// We log sender reports, receiver reports, bye messages
|
|
|
|
|
// inter-arrival jitter, third-party loss reports, payload-specific
|
|
|
|
|
// feedback and extended reports.
|
|
|
|
|
memcpy(buffer + buffer_length, block_begin, block_size);
|
|
|
|
|
buffer_length += block_size;
|
|
|
|
|
break;
|
|
|
|
|
case RTCPUtility::PT_SDES:
|
|
|
|
|
FALLTHROUGH();
|
|
|
|
|
case RTCPUtility::PT_APP:
|
|
|
|
|
FALLTHROUGH();
|
|
|
|
|
default:
|
|
|
|
|
// We don't log sender descriptions, application defined messages
|
|
|
|
|
// or message blocks of unknown type.
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block_begin += block_size;
|
|
|
|
|
}
|
2016-04-22 12:40:37 -07:00
|
|
|
rtcp_event->mutable_rtcp_packet()->set_packet_data(buffer, buffer_length);
|
2016-06-08 07:20:29 -07:00
|
|
|
StoreEvent(&rtcp_event);
|
2015-07-30 12:45:18 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-17 16:30:16 +02:00
|
|
|
void RtcEventLogImpl::LogAudioPlayout(uint32_t ssrc) {
|
2016-04-22 12:40:37 -07:00
|
|
|
std::unique_ptr<rtclog::Event> event(new rtclog::Event());
|
|
|
|
|
event->set_timestamp_us(clock_->TimeInMicroseconds());
|
|
|
|
|
event->set_type(rtclog::Event::AUDIO_PLAYOUT_EVENT);
|
|
|
|
|
auto playout_event = event->mutable_audio_playout_event();
|
2015-10-08 18:07:41 +02:00
|
|
|
playout_event->set_local_ssrc(ssrc);
|
2016-06-08 07:20:29 -07:00
|
|
|
StoreEvent(&event);
|
2015-07-30 12:45:18 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-05 12:02:15 -08:00
|
|
|
void RtcEventLogImpl::LogBwePacketLossEvent(int32_t bitrate,
|
|
|
|
|
uint8_t fraction_loss,
|
|
|
|
|
int32_t total_packets) {
|
2016-04-22 12:40:37 -07:00
|
|
|
std::unique_ptr<rtclog::Event> event(new rtclog::Event());
|
|
|
|
|
event->set_timestamp_us(clock_->TimeInMicroseconds());
|
|
|
|
|
event->set_type(rtclog::Event::BWE_PACKET_LOSS_EVENT);
|
|
|
|
|
auto bwe_event = event->mutable_bwe_packet_loss_event();
|
2015-11-05 12:02:15 -08:00
|
|
|
bwe_event->set_bitrate(bitrate);
|
|
|
|
|
bwe_event->set_fraction_loss(fraction_loss);
|
|
|
|
|
bwe_event->set_total_packets(total_packets);
|
2016-06-08 07:20:29 -07:00
|
|
|
StoreEvent(&event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RtcEventLogImpl::StoreEvent(std::unique_ptr<rtclog::Event>* event) {
|
|
|
|
|
if (!event_queue_.Insert(event)) {
|
|
|
|
|
LOG(LS_ERROR) << "WebRTC event log queue full. Dropping event.";
|
2015-07-30 12:45:18 +02:00
|
|
|
}
|
2016-06-08 07:20:29 -07:00
|
|
|
helper_thread_.SignalNewEvent();
|
2015-07-30 12:45:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool RtcEventLog::ParseRtcEventLog(const std::string& file_name,
|
|
|
|
|
rtclog::EventStream* result) {
|
|
|
|
|
char tmp_buffer[1024];
|
|
|
|
|
int bytes_read = 0;
|
2016-03-12 06:10:44 -08:00
|
|
|
std::unique_ptr<FileWrapper> dump_file(FileWrapper::Create());
|
FileWrapper[Impl] modifications and actually remove the "Impl" class.
This is a somewhat involved refactoring of this class. Here's an overview of the changes:
* FileWrapper can now be used as a regular class and instances allocated on the stack.
* The type now has support for move semantics and copy isn't allowed.
* New public ctor with FILE* that can be used instead of OpenFromFileHandle.
* New static Open() method. The intent of this is to allow opening a file and getting back a FileWrapper instance. Using this method instead of Create(), will allow us in the future to make the FILE* member pointer, to be const and simplify threading (get rid of the lock).
* Rename the Open() method to is_open() and make it inline.
* The FileWrapper interface is no longer a pure virtual interface. There's only one implementation so there's no need to go through a vtable for everything.
* Functionality offered by the class, is now reduced. No support for looping (not clear if that was actually useful to users of that flag), no need to implement the 'read_only_' functionality in the class, since file APIs implement that already, no support for *not* managing the file handle (this wasn't used). OpenFromFileHandle always "manages" the file.
* Delete the unused WriteText() method and don't support opening files in text mode. Text mode is only different on Windows and on Windows it translates \n to \r\n, which means that files such as log files, could have a slightly different format on Windows than other platforms. Besides, tools on Windows can handle UNIX line endings.
* Remove FileName(), change Trace code to manage its own path.
* Rename id_ member variable to file_.
* Removed the open_ member variable since the same functionality can be gotten from just checking the file pointer.
* Don't call CloseFile inside of Write. Write shouldn't be changing the state of the class beyond just attempting to write.
* Remove concept of looping from FileWrapper and never close inside of Read()
* Changed stream base classes to inherit from a common base class instead of both defining the Rewind method. Ultimately, Id' like to remove these interfaces and just have FileWrapper.
* Remove read_only param from OpenFromFileHandle
* Renamed size_in_bytes_ to position_, since it gets set to 0 when Rewind() is called (and the size actually does not change).
* Switch out rw lock for CriticalSection. The r/w lock was only used for reading when checking the open_ flag.
BUG=
Review-Url: https://codereview.webrtc.org/2054373002
Cr-Commit-Position: refs/heads/master@{#13155}
2016-06-15 10:30:14 -07:00
|
|
|
if (!dump_file->OpenFile(file_name.c_str(), true)) {
|
2015-07-30 12:45:18 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
std::string dump_buffer;
|
|
|
|
|
while ((bytes_read = dump_file->Read(tmp_buffer, sizeof(tmp_buffer))) > 0) {
|
|
|
|
|
dump_buffer.append(tmp_buffer, bytes_read);
|
|
|
|
|
}
|
|
|
|
|
dump_file->CloseFile();
|
|
|
|
|
return result->ParseFromString(dump_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // ENABLE_RTC_EVENT_LOG
|
|
|
|
|
|
|
|
|
|
// RtcEventLog member functions.
|
2016-04-22 12:40:37 -07:00
|
|
|
std::unique_ptr<RtcEventLog> RtcEventLog::Create(const Clock* clock) {
|
|
|
|
|
#ifdef ENABLE_RTC_EVENT_LOG
|
|
|
|
|
return std::unique_ptr<RtcEventLog>(new RtcEventLogImpl(clock));
|
|
|
|
|
#else
|
|
|
|
|
return std::unique_ptr<RtcEventLog>(new RtcEventLogNullImpl());
|
|
|
|
|
#endif // ENABLE_RTC_EVENT_LOG
|
2015-07-30 12:45:18 +02:00
|
|
|
}
|
2015-10-16 08:51:08 -07:00
|
|
|
|
2015-07-30 12:45:18 +02:00
|
|
|
} // namespace webrtc
|