Implement standalone event tracing in AppRTCDemo.

Logs tracing events (TRACE_EVENT0 and friends) to storage in a format
compatible with chrome://tracing which can be used for performance
evaluation, finding lock contention and other sweet things). Tracing is
still basic and doesn't contain thread metadata or logging of tracing
arguments.

BUG=webrtc:5158
R=tommi@webrtc.org

Review URL: https://codereview.webrtc.org/1457383002 .

Cr-Commit-Position: refs/heads/master@{#10921}
This commit is contained in:
Peter Boström
2015-12-07 23:17:15 +01:00
parent 84f0970d10
commit 6f28cf0b95
14 changed files with 321 additions and 10 deletions

View File

@ -74,10 +74,11 @@
#include "talk/media/webrtc/webrtcvideoencoderfactory.h" #include "talk/media/webrtc/webrtcvideoencoderfactory.h"
#include "webrtc/base/bind.h" #include "webrtc/base/bind.h"
#include "webrtc/base/checks.h" #include "webrtc/base/checks.h"
#include "webrtc/base/event_tracer.h"
#include "webrtc/base/logging.h" #include "webrtc/base/logging.h"
#include "webrtc/base/logsinks.h" #include "webrtc/base/logsinks.h"
#include "webrtc/base/networkmonitor.h"
#include "webrtc/base/messagequeue.h" #include "webrtc/base/messagequeue.h"
#include "webrtc/base/networkmonitor.h"
#include "webrtc/base/ssladapter.h" #include "webrtc/base/ssladapter.h"
#include "webrtc/base/stringutils.h" #include "webrtc/base/stringutils.h"
#include "webrtc/system_wrappers/include/field_trial_default.h" #include "webrtc/system_wrappers/include/field_trial_default.h"
@ -1054,6 +1055,32 @@ JOW(void, PeerConnectionFactory_initializeFieldTrials)(
webrtc::field_trial::InitFieldTrialsFromString(field_trials_init_string); webrtc::field_trial::InitFieldTrialsFromString(field_trials_init_string);
} }
JOW(void, PeerConnectionFactory_initializeInternalTracer)(JNIEnv* jni, jclass) {
rtc::tracing::SetupInternalTracer();
}
JOW(jboolean, PeerConnectionFactory_startInternalTracingCapture)(
JNIEnv* jni, jclass, jstring j_event_tracing_filename) {
if (!j_event_tracing_filename)
return false;
const char* init_string =
jni->GetStringUTFChars(j_event_tracing_filename, NULL);
LOG(LS_INFO) << "Starting internal tracing to: " << init_string;
bool ret = rtc::tracing::StartInternalCapture(init_string);
jni->ReleaseStringUTFChars(j_event_tracing_filename, init_string);
return ret;
}
JOW(void, PeerConnectionFactory_stopInternalTracingCapture)(
JNIEnv* jni, jclass) {
rtc::tracing::StopInternalCapture();
}
JOW(void, PeerConnectionFactory_shutdownInternalTracer)(JNIEnv* jni, jclass) {
rtc::tracing::ShutdownInternalTracer();
}
// Helper struct for working around the fact that CreatePeerConnectionFactory() // Helper struct for working around the fact that CreatePeerConnectionFactory()
// comes in two flavors: either entirely automagical (constructing its own // comes in two flavors: either entirely automagical (constructing its own
// threads and deleting them on teardown, but no external codec factory support) // threads and deleting them on teardown, but no external codec factory support)

View File

@ -73,6 +73,15 @@ public class PeerConnectionFactory {
// Field trial initialization. Must be called before PeerConnectionFactory // Field trial initialization. Must be called before PeerConnectionFactory
// is created. // is created.
public static native void initializeFieldTrials(String fieldTrialsInitString); public static native void initializeFieldTrials(String fieldTrialsInitString);
// Internal tracing initialization. Must be called before PeerConnectionFactory is created to
// prevent racing with tracing code.
public static native void initializeInternalTracer();
// Internal tracing shutdown, called to prevent resource leaks. Must be called after
// PeerConnectionFactory is gone to prevent races with code performing tracing.
public static native void shutdownInternalTracer();
// Start/stop internal capturing of internal tracing.
public static native boolean startInternalTracingCapture(String tracing_filename);
public static native void stopInternalTracingCapture();
public PeerConnectionFactory() { public PeerConnectionFactory() {
nativeFactory = nativeCreatePeerConnectionFactory(); nativeFactory = nativeCreatePeerConnectionFactory();

View File

@ -29,7 +29,6 @@
#include "talk/media/base/constants.h" #include "talk/media/base/constants.h"
#include "talk/media/base/rtputils.h" #include "talk/media/base/rtputils.h"
#include "webrtc/p2p/base/transportchannel.h"
#include "talk/session/media/channelmanager.h" #include "talk/session/media/channelmanager.h"
#include "webrtc/base/bind.h" #include "webrtc/base/bind.h"
#include "webrtc/base/buffer.h" #include "webrtc/base/buffer.h"
@ -37,6 +36,8 @@
#include "webrtc/base/common.h" #include "webrtc/base/common.h"
#include "webrtc/base/dscp.h" #include "webrtc/base/dscp.h"
#include "webrtc/base/logging.h" #include "webrtc/base/logging.h"
#include "webrtc/base/trace_event.h"
#include "webrtc/p2p/base/transportchannel.h"
namespace cricket { namespace cricket {
@ -471,6 +472,7 @@ void BaseChannel::OnChannelRead(TransportChannel* channel,
const char* data, size_t len, const char* data, size_t len,
const rtc::PacketTime& packet_time, const rtc::PacketTime& packet_time,
int flags) { int flags) {
TRACE_EVENT0("webrtc", "BaseChannel::OnChannelRead");
// OnChannelRead gets called from P2PSocket; now pass data to MediaEngine // OnChannelRead gets called from P2PSocket; now pass data to MediaEngine
ASSERT(worker_thread_ == rtc::Thread::Current()); ASSERT(worker_thread_ == rtc::Thread::Current());
@ -1272,6 +1274,7 @@ void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension(
} }
void BaseChannel::OnMessage(rtc::Message *pmsg) { void BaseChannel::OnMessage(rtc::Message *pmsg) {
TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
switch (pmsg->message_id) { switch (pmsg->message_id) {
case MSG_RTPPACKET: case MSG_RTPPACKET:
case MSG_RTCPPACKET: { case MSG_RTCPPACKET: {

View File

@ -43,6 +43,16 @@ class AtomicOps {
new_value, new_value,
old_value); old_value);
} }
// Pointer variants.
template <typename T>
static T* AtomicLoadPtr(T* volatile* ptr) {
return *ptr;
}
template <typename T>
static T* CompareAndSwapPtr(T* volatile* ptr, T* old_value, T* new_value) {
return static_cast<T*>(::InterlockedCompareExchangePointer(
reinterpret_cast<PVOID volatile*>(ptr), old_value, new_value));
}
#else #else
static int Increment(volatile int* i) { static int Increment(volatile int* i) {
return __sync_add_and_fetch(i, 1); return __sync_add_and_fetch(i, 1);
@ -59,6 +69,15 @@ class AtomicOps {
static int CompareAndSwap(volatile int* i, int old_value, int new_value) { static int CompareAndSwap(volatile int* i, int old_value, int new_value) {
return __sync_val_compare_and_swap(i, old_value, new_value); return __sync_val_compare_and_swap(i, old_value, new_value);
} }
// Pointer variants.
template <typename T>
static T* AtomicLoadPtr(T* volatile* ptr) {
return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
}
template <typename T>
static T* CompareAndSwapPtr(T* volatile* ptr, T* old_value, T* new_value) {
return __sync_val_compare_and_swap(ptr, old_value, new_value);
}
#endif #endif
}; };

View File

@ -7,15 +7,26 @@
* in the file PATENTS. All contributing project authors may * in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "webrtc/base/event_tracer.h" #include "webrtc/base/event_tracer.h"
#include <inttypes.h>
#include <vector>
#include "webrtc/base/checks.h"
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/event.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/platform_thread.h"
#include "webrtc/base/timeutils.h"
#include "webrtc/base/trace_event.h"
namespace webrtc { namespace webrtc {
namespace { namespace {
GetCategoryEnabledPtr g_get_category_enabled_ptr = 0; GetCategoryEnabledPtr g_get_category_enabled_ptr = nullptr;
AddTraceEventPtr g_add_trace_event_ptr = 0; AddTraceEventPtr g_add_trace_event_ptr = nullptr;
} // namespace } // namespace
@ -25,7 +36,6 @@ void SetupEventTracer(GetCategoryEnabledPtr get_category_enabled_ptr,
g_add_trace_event_ptr = add_trace_event_ptr; g_add_trace_event_ptr = add_trace_event_ptr;
} }
// static
const unsigned char* EventTracer::GetCategoryEnabled(const char* name) { const unsigned char* EventTracer::GetCategoryEnabled(const char* name) {
if (g_get_category_enabled_ptr) if (g_get_category_enabled_ptr)
return g_get_category_enabled_ptr(name); return g_get_category_enabled_ptr(name);
@ -34,7 +44,8 @@ const unsigned char* EventTracer::GetCategoryEnabled(const char* name) {
return reinterpret_cast<const unsigned char*>("\0"); return reinterpret_cast<const unsigned char*>("\0");
} }
// static // Arguments to this function (phase, etc.) are as defined in
// webrtc/base/trace_event.h.
void EventTracer::AddTraceEvent(char phase, void EventTracer::AddTraceEvent(char phase,
const unsigned char* category_enabled, const unsigned char* category_enabled,
const char* name, const char* name,
@ -58,3 +69,197 @@ void EventTracer::AddTraceEvent(char phase,
} }
} // namespace webrtc } // namespace webrtc
namespace rtc {
namespace tracing {
namespace {
static bool EventTracingThreadFunc(void* params);
// Atomic-int fast path for avoiding logging when disabled.
static volatile int g_event_logging_active = 0;
// TODO(pbos): Log metadata for all threads, etc.
class EventLogger final {
public:
EventLogger()
: logging_thread_(EventTracingThreadFunc, this, "EventTracingThread"),
shutdown_event_(false, false) {}
~EventLogger() { RTC_DCHECK(thread_checker_.CalledOnValidThread()); }
void AddTraceEvent(const char* name,
const unsigned char* category_enabled,
char phase,
uint64_t timestamp,
int pid,
rtc::PlatformThreadId thread_id) {
rtc::CritScope lock(&crit_);
trace_events_.push_back(
{name, category_enabled, phase, timestamp, 1, thread_id});
}
// The TraceEvent format is documented here:
// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
void Log() {
RTC_DCHECK(output_file_);
static const int kLoggingIntervalMs = 100;
fprintf(output_file_, "{ \"traceEvents\": [\n");
bool has_logged_event = false;
while (true) {
bool shutting_down = shutdown_event_.Wait(kLoggingIntervalMs);
std::vector<TraceEvent> events;
{
rtc::CritScope lock(&crit_);
trace_events_.swap(events);
}
for (const TraceEvent& e : events) {
fprintf(output_file_,
"%s{ \"name\": \"%s\""
", \"cat\": \"%s\""
", \"ph\": \"%c\""
", \"ts\": %" PRIu64
", \"pid\": %d"
", \"tid\": %d}\n",
has_logged_event ? "," : " ", e.name, e.category_enabled,
e.phase, e.timestamp, e.pid, e.tid);
has_logged_event = true;
}
if (shutting_down)
break;
}
fprintf(output_file_, "]}\n");
if (output_file_owned_)
fclose(output_file_);
output_file_ = nullptr;
}
void Start(FILE* file, bool owned) {
RTC_DCHECK(file);
RTC_DCHECK(!output_file_);
output_file_ = file;
output_file_owned_ = owned;
{
rtc::CritScope lock(&crit_);
// Since the atomic fast-path for adding events to the queue can be
// bypassed while the logging thread is shutting down there may be some
// stale events in the queue, hence the vector needs to be cleared to not
// log events from a previous logging session (which may be days old).
trace_events_.clear();
}
// Enable event logging (fast-path). This should be disabled since starting
// shouldn't be done twice.
RTC_CHECK_EQ(0,
rtc::AtomicOps::CompareAndSwap(&g_event_logging_active, 0, 1));
// Finally start, everything should be set up now.
logging_thread_.Start();
}
void Stop() {
// Try to stop. Abort if we're not currently logging.
if (rtc::AtomicOps::CompareAndSwap(&g_event_logging_active, 1, 0) == 0)
return;
// Wake up logging thread to finish writing.
shutdown_event_.Set();
// Join the logging thread.
logging_thread_.Stop();
}
private:
struct TraceEvent {
const char* name;
const unsigned char* category_enabled;
char phase;
uint64_t timestamp;
int pid;
rtc::PlatformThreadId tid;
};
rtc::CriticalSection crit_;
std::vector<TraceEvent> trace_events_ GUARDED_BY(crit_);
rtc::PlatformThread logging_thread_;
rtc::Event shutdown_event_;
rtc::ThreadChecker thread_checker_;
FILE* output_file_ = nullptr;
bool output_file_owned_ = false;
};
static bool EventTracingThreadFunc(void* params) {
static_cast<EventLogger*>(params)->Log();
return true;
}
static EventLogger* volatile g_event_logger = nullptr;
static const char* const kDisabledTracePrefix = TRACE_DISABLED_BY_DEFAULT("");
const unsigned char* InternalGetCategoryEnabled(const char* name) {
const char* prefix_ptr = &kDisabledTracePrefix[0];
const char* name_ptr = name;
// Check whether name contains the default-disabled prefix.
while (*prefix_ptr == *name_ptr && *prefix_ptr != '\0') {
++prefix_ptr;
++name_ptr;
}
return reinterpret_cast<const unsigned char*>(*prefix_ptr == '\0' ? ""
: name);
}
void InternalAddTraceEvent(char phase,
const unsigned char* category_enabled,
const char* name,
unsigned long long id,
int num_args,
const char** arg_names,
const unsigned char* arg_types,
const unsigned long long* arg_values,
unsigned char flags) {
// Fast path for when event tracing is inactive.
if (rtc::AtomicOps::AcquireLoad(&g_event_logging_active) == 0)
return;
g_event_logger->AddTraceEvent(name, category_enabled, phase,
rtc::TimeMicros(), 1, rtc::CurrentThreadId());
}
} // namespace
void SetupInternalTracer() {
RTC_CHECK(rtc::AtomicOps::CompareAndSwapPtr(
&g_event_logger, static_cast<EventLogger*>(nullptr),
new EventLogger()) == nullptr);
g_event_logger = new EventLogger();
webrtc::SetupEventTracer(InternalGetCategoryEnabled, InternalAddTraceEvent);
}
void StartInternalCaptureToFile(FILE* file) {
g_event_logger->Start(file, false);
}
bool StartInternalCapture(const char* filename) {
FILE* file = fopen(filename, "w");
if (!file) {
LOG(LS_ERROR) << "Failed to open trace file '" << filename
<< "' for writing.";
return false;
}
g_event_logger->Start(file, true);
return true;
}
void StopInternalCapture() {
g_event_logger->Stop();
}
void ShutdownInternalTracer() {
StopInternalCapture();
EventLogger* old_logger = rtc::AtomicOps::AtomicLoadPtr(&g_event_logger);
RTC_DCHECK(old_logger);
RTC_CHECK(rtc::AtomicOps::CompareAndSwapPtr(
&g_event_logger, old_logger,
static_cast<EventLogger*>(nullptr)) == old_logger);
delete old_logger;
webrtc::SetupEventTracer(nullptr, nullptr);
}
} // namespace tracing
} // namespace rtc

View File

@ -26,6 +26,8 @@
#ifndef WEBRTC_BASE_EVENT_TRACER_H_ #ifndef WEBRTC_BASE_EVENT_TRACER_H_
#define WEBRTC_BASE_EVENT_TRACER_H_ #define WEBRTC_BASE_EVENT_TRACER_H_
#include <stdio.h>
namespace webrtc { namespace webrtc {
typedef const unsigned char* (*GetCategoryEnabledPtr)(const char* name); typedef const unsigned char* (*GetCategoryEnabledPtr)(const char* name);
@ -68,4 +70,16 @@ class EventTracer {
} // namespace webrtc } // namespace webrtc
namespace rtc {
namespace tracing {
// Set up internal event tracer.
void SetupInternalTracer();
bool StartInternalCapture(const char* filename);
void StartInternalCaptureToFile(FILE* file);
void StopInternalCapture();
// Make sure we run this, this will tear down the internal tracing.
void ShutdownInternalTracer();
} // namespace tracing
} // namespace rtc
#endif // WEBRTC_BASE_EVENT_TRACER_H_ #endif // WEBRTC_BASE_EVENT_TRACER_H_

View File

@ -655,6 +655,7 @@ void Call::ConfigureSync(const std::string& sync_group) {
PacketReceiver::DeliveryStatus Call::DeliverRtcp(MediaType media_type, PacketReceiver::DeliveryStatus Call::DeliverRtcp(MediaType media_type,
const uint8_t* packet, const uint8_t* packet,
size_t length) { size_t length) {
TRACE_EVENT0("webrtc", "Call::DeliverRtcp");
// TODO(pbos): Figure out what channel needs it actually. // TODO(pbos): Figure out what channel needs it actually.
// Do NOT broadcast! Also make sure it's a valid packet. // Do NOT broadcast! Also make sure it's a valid packet.
// Return DELIVERY_UNKNOWN_SSRC if it can be determined that // Return DELIVERY_UNKNOWN_SSRC if it can be determined that
@ -688,6 +689,7 @@ PacketReceiver::DeliveryStatus Call::DeliverRtp(MediaType media_type,
const uint8_t* packet, const uint8_t* packet,
size_t length, size_t length,
const PacketTime& packet_time) { const PacketTime& packet_time) {
TRACE_EVENT0("webrtc", "Call::DeliverRtp");
// Minimum RTP header size. // Minimum RTP header size.
if (length < 12) if (length < 12)
return DELIVERY_PACKET_ERROR; return DELIVERY_PACKET_ERROR;

View File

@ -120,4 +120,9 @@
<string name="pref_displayhud_dlg">Display call statistics.</string> <string name="pref_displayhud_dlg">Display call statistics.</string>
<string name="pref_displayhud_default" translatable="false">false</string> <string name="pref_displayhud_default" translatable="false">false</string>
<string name="pref_tracing_key">tracing_preference</string>
<string name="pref_tracing_title">Debug performance tracing.</string>
<string name="pref_tracing_dlg">Debug performance tracing.</string>
<string name="pref_tracing_default" translatable="false">false</string>
</resources> </resources>

View File

@ -124,6 +124,12 @@
android:title="@string/pref_displayhud_title" android:title="@string/pref_displayhud_title"
android:dialogTitle="@string/pref_displayhud_dlg" android:dialogTitle="@string/pref_displayhud_dlg"
android:defaultValue="@string/pref_displayhud_default" /> android:defaultValue="@string/pref_displayhud_default" />
<CheckBoxPreference
android:key="@string/pref_tracing_key"
android:title="@string/pref_tracing_title"
android:dialogTitle="@string/pref_tracing_dlg"
android:defaultValue="@string/pref_tracing_default" />
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View File

@ -78,6 +78,7 @@ public class CallActivity extends Activity
"org.appspot.apprtc.OPENSLES"; "org.appspot.apprtc.OPENSLES";
public static final String EXTRA_DISPLAY_HUD = public static final String EXTRA_DISPLAY_HUD =
"org.appspot.apprtc.DISPLAY_HUD"; "org.appspot.apprtc.DISPLAY_HUD";
public static final String EXTRA_TRACING = "org.appspot.apprtc.TRACING";
public static final String EXTRA_CMDLINE = public static final String EXTRA_CMDLINE =
"org.appspot.apprtc.CMDLINE"; "org.appspot.apprtc.CMDLINE";
public static final String EXTRA_RUNTIME = public static final String EXTRA_RUNTIME =
@ -213,9 +214,11 @@ public class CallActivity extends Activity
return; return;
} }
boolean loopback = intent.getBooleanExtra(EXTRA_LOOPBACK, false); boolean loopback = intent.getBooleanExtra(EXTRA_LOOPBACK, false);
boolean tracing = intent.getBooleanExtra(EXTRA_TRACING, false);
peerConnectionParameters = new PeerConnectionParameters( peerConnectionParameters = new PeerConnectionParameters(
intent.getBooleanExtra(EXTRA_VIDEO_CALL, true), intent.getBooleanExtra(EXTRA_VIDEO_CALL, true),
loopback, loopback,
tracing,
intent.getIntExtra(EXTRA_VIDEO_WIDTH, 0), intent.getIntExtra(EXTRA_VIDEO_WIDTH, 0),
intent.getIntExtra(EXTRA_VIDEO_HEIGHT, 0), intent.getIntExtra(EXTRA_VIDEO_HEIGHT, 0),
intent.getIntExtra(EXTRA_VIDEO_FPS, 0), intent.getIntExtra(EXTRA_VIDEO_FPS, 0),

View File

@ -69,6 +69,7 @@ public class ConnectActivity extends Activity {
private String keyprefNoAudioProcessingPipeline; private String keyprefNoAudioProcessingPipeline;
private String keyprefOpenSLES; private String keyprefOpenSLES;
private String keyprefDisplayHud; private String keyprefDisplayHud;
private String keyprefTracing;
private String keyprefRoomServerUrl; private String keyprefRoomServerUrl;
private String keyprefRoom; private String keyprefRoom;
private String keyprefRoomList; private String keyprefRoomList;
@ -97,6 +98,7 @@ public class ConnectActivity extends Activity {
keyprefNoAudioProcessingPipeline = getString(R.string.pref_noaudioprocessing_key); keyprefNoAudioProcessingPipeline = getString(R.string.pref_noaudioprocessing_key);
keyprefOpenSLES = getString(R.string.pref_opensles_key); keyprefOpenSLES = getString(R.string.pref_opensles_key);
keyprefDisplayHud = getString(R.string.pref_displayhud_key); keyprefDisplayHud = getString(R.string.pref_displayhud_key);
keyprefTracing = getString(R.string.pref_tracing_key);
keyprefRoomServerUrl = getString(R.string.pref_room_server_url_key); keyprefRoomServerUrl = getString(R.string.pref_room_server_url_key);
keyprefRoom = getString(R.string.pref_room_key); keyprefRoom = getString(R.string.pref_room_key);
keyprefRoomList = getString(R.string.pref_room_list_key); keyprefRoomList = getString(R.string.pref_room_list_key);
@ -328,6 +330,9 @@ public class ConnectActivity extends Activity {
boolean displayHud = sharedPref.getBoolean(keyprefDisplayHud, boolean displayHud = sharedPref.getBoolean(keyprefDisplayHud,
Boolean.valueOf(getString(R.string.pref_displayhud_default))); Boolean.valueOf(getString(R.string.pref_displayhud_default)));
boolean tracing = sharedPref.getBoolean(
keyprefTracing, Boolean.valueOf(getString(R.string.pref_tracing_default)));
// Start AppRTCDemo activity. // Start AppRTCDemo activity.
Log.d(TAG, "Connecting to room " + roomId + " at URL " + roomUrl); Log.d(TAG, "Connecting to room " + roomId + " at URL " + roomUrl);
if (validateUrl(roomUrl)) { if (validateUrl(roomUrl)) {
@ -352,6 +357,7 @@ public class ConnectActivity extends Activity {
intent.putExtra(CallActivity.EXTRA_AUDIO_BITRATE, audioStartBitrate); intent.putExtra(CallActivity.EXTRA_AUDIO_BITRATE, audioStartBitrate);
intent.putExtra(CallActivity.EXTRA_AUDIOCODEC, audioCodec); intent.putExtra(CallActivity.EXTRA_AUDIOCODEC, audioCodec);
intent.putExtra(CallActivity.EXTRA_DISPLAY_HUD, displayHud); intent.putExtra(CallActivity.EXTRA_DISPLAY_HUD, displayHud);
intent.putExtra(CallActivity.EXTRA_TRACING, tracing);
intent.putExtra(CallActivity.EXTRA_CMDLINE, commandLineRun); intent.putExtra(CallActivity.EXTRA_CMDLINE, commandLineRun);
intent.putExtra(CallActivity.EXTRA_RUNTIME, runTimeMs); intent.putExtra(CallActivity.EXTRA_RUNTIME, runTimeMs);

View File

@ -128,6 +128,7 @@ public class PeerConnectionClient {
public static class PeerConnectionParameters { public static class PeerConnectionParameters {
public final boolean videoCallEnabled; public final boolean videoCallEnabled;
public final boolean loopback; public final boolean loopback;
public final boolean tracing;
public final int videoWidth; public final int videoWidth;
public final int videoHeight; public final int videoHeight;
public final int videoFps; public final int videoFps;
@ -141,13 +142,14 @@ public class PeerConnectionClient {
public final boolean useOpenSLES; public final boolean useOpenSLES;
public PeerConnectionParameters( public PeerConnectionParameters(
boolean videoCallEnabled, boolean loopback, boolean videoCallEnabled, boolean loopback, boolean tracing,
int videoWidth, int videoHeight, int videoFps, int videoStartBitrate, int videoWidth, int videoHeight, int videoFps, int videoStartBitrate,
String videoCodec, boolean videoCodecHwAcceleration, boolean captureToTexture, String videoCodec, boolean videoCodecHwAcceleration, boolean captureToTexture,
int audioStartBitrate, String audioCodec, int audioStartBitrate, String audioCodec,
boolean noAudioProcessing, boolean useOpenSLES) { boolean noAudioProcessing, boolean useOpenSLES) {
this.videoCallEnabled = videoCallEnabled; this.videoCallEnabled = videoCallEnabled;
this.loopback = loopback; this.loopback = loopback;
this.tracing = tracing;
this.videoWidth = videoWidth; this.videoWidth = videoWidth;
this.videoHeight = videoHeight; this.videoHeight = videoHeight;
this.videoFps = videoFps; this.videoFps = videoFps;
@ -285,6 +287,10 @@ public class PeerConnectionClient {
} }
private void createPeerConnectionFactoryInternal(Context context) { private void createPeerConnectionFactoryInternal(Context context) {
PeerConnectionFactory.initializeInternalTracer();
if (peerConnectionParameters.tracing) {
PeerConnectionFactory.startInternalTracingCapture("/mnt/sdcard/webrtc-trace.txt");
}
Log.d(TAG, "Create peer connection factory. Use video: " + Log.d(TAG, "Create peer connection factory. Use video: " +
peerConnectionParameters.videoCallEnabled); peerConnectionParameters.videoCallEnabled);
isError = false; isError = false;
@ -502,6 +508,8 @@ public class PeerConnectionClient {
options = null; options = null;
Log.d(TAG, "Closing peer connection done."); Log.d(TAG, "Closing peer connection done.");
events.onPeerConnectionClosed(); events.onPeerConnectionClosed();
PeerConnectionFactory.stopInternalTracingCapture();
PeerConnectionFactory.shutdownInternalTracer();
} }
public boolean isHDVideo() { public boolean isHDVideo() {

View File

@ -40,6 +40,7 @@ public class SettingsActivity extends Activity
private String keyPrefRoomServerUrl; private String keyPrefRoomServerUrl;
private String keyPrefDisplayHud; private String keyPrefDisplayHud;
private String keyPrefTracing;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -62,6 +63,7 @@ public class SettingsActivity extends Activity
keyPrefRoomServerUrl = getString(R.string.pref_room_server_url_key); keyPrefRoomServerUrl = getString(R.string.pref_room_server_url_key);
keyPrefDisplayHud = getString(R.string.pref_displayhud_key); keyPrefDisplayHud = getString(R.string.pref_displayhud_key);
keyPrefTracing = getString(R.string.pref_tracing_key);
// Display the fragment as the main content. // Display the fragment as the main content.
settingsFragment = new SettingsFragment(); settingsFragment = new SettingsFragment();
@ -97,6 +99,7 @@ public class SettingsActivity extends Activity
updateSummary(sharedPreferences, keyPrefRoomServerUrl); updateSummary(sharedPreferences, keyPrefRoomServerUrl);
updateSummaryB(sharedPreferences, keyPrefDisplayHud); updateSummaryB(sharedPreferences, keyPrefDisplayHud);
updateSummaryB(sharedPreferences, keyPrefTracing);
} }
@Override @Override
@ -122,6 +125,7 @@ public class SettingsActivity extends Activity
|| key.equals(keyprefStartAudioBitrateValue)) { || key.equals(keyprefStartAudioBitrateValue)) {
updateSummaryBitrate(sharedPreferences, key); updateSummaryBitrate(sharedPreferences, key);
} else if (key.equals(keyprefVideoCall) } else if (key.equals(keyprefVideoCall)
|| key.equals(keyPrefTracing)
|| key.equals(keyprefCaptureQualitySlider) || key.equals(keyprefCaptureQualitySlider)
|| key.equals(keyprefHwCodec) || key.equals(keyprefHwCodec)
|| key.equals(keyprefCaptureToTexture) || key.equals(keyprefCaptureToTexture)

View File

@ -249,7 +249,7 @@ public class PeerConnectionClientTest extends InstrumentationTestCase
private PeerConnectionParameters createParametersForAudioCall() { private PeerConnectionParameters createParametersForAudioCall() {
PeerConnectionParameters peerConnectionParameters = PeerConnectionParameters peerConnectionParameters =
new PeerConnectionParameters( new PeerConnectionParameters(
false, true, // videoCallEnabled, loopback. false, true, false, // videoCallEnabled, loopback, tracing.
0, 0, 0, 0, "", true, false, // video codec parameters. 0, 0, 0, 0, "", true, false, // video codec parameters.
0, "OPUS", false, false); // audio codec parameters. 0, "OPUS", false, false); // audio codec parameters.
return peerConnectionParameters; return peerConnectionParameters;
@ -259,7 +259,7 @@ public class PeerConnectionClientTest extends InstrumentationTestCase
String videoCodec, boolean captureToTexture) { String videoCodec, boolean captureToTexture) {
PeerConnectionParameters peerConnectionParameters = PeerConnectionParameters peerConnectionParameters =
new PeerConnectionParameters( new PeerConnectionParameters(
true, true, // videoCallEnabled, loopback. true, true, false, // videoCallEnabled, loopback, tracing.
0, 0, 0, 0, videoCodec, true, captureToTexture, // video codec parameters. 0, 0, 0, 0, videoCodec, true, captureToTexture, // video codec parameters.
0, "OPUS", false, false); // audio codec parameters. 0, "OPUS", false, false); // audio codec parameters.
return peerConnectionParameters; return peerConnectionParameters;